Skip to content

Commit

Permalink
Changed default middle C octave to 3 for note names, which is the mos…
Browse files Browse the repository at this point in the history
…t common one.

Added support for virtual MIDI input ports on Linux and macOS.
  • Loading branch information
gbevin committed Feb 28, 2017
1 parent bc5a8d7 commit d90c2b3
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 23 deletions.
16 changes: 9 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,16 @@ To use it, simply type "receivemidi" or "receivemidi.exe" on the command line an

These are all the supported commands:
```
dev name Set the name of the MIDI input port (REQUIRED)
dev name Set the name of the MIDI input port
virt (name) Use virtual MIDI port with optional name (Linux/macOS)
list Lists the MIDI input ports
file path Loads commands from the specified program file
dec Interpret the next numbers as decimals by default
hex Interpret the next numbers as hexadecimals by default
ch number Set MIDI channel for the commands (0-16), defaults to 0
ts Output a timestamp for each received MIDI message
nn Output notes as numbers instead of names
omc number Set octave for middle C, defaults to 5
omc number Set octave for middle C, defaults to 3
voice Show all Channel Voice messages
note Show all Note messages
on (note) Show Note On, optionally for note (0-127)
Expand Down Expand Up @@ -66,10 +67,11 @@ These are all the supported commands:

Alternatively, you can use the following long versions of the commands:
```
device decimal hexadecimal channel timestamp note-numbers octave-middle-c
note-on note-off poly-pressure control-change program-change channel-pressure
pitch-bend system-realtime continue active-sensing reset system-common
system-exclusive time-code song-position song-select tune-request
device virtual decimal hexadecimal channel timestamp note-numbers
octave-middle-c note-on note-off poly-pressure control-change program-change
channel-pressure pitch-bend system-realtime continue active-sensing reset
system-common system-exclusive time-code song-position song-select
tune-request
```

By default, numbers are interpreted in the decimal system, this can be changed to hexadecimal by sending the "hex" command.
Expand All @@ -78,7 +80,7 @@ Additionally, by suffixing a number with "M" or "H", it will be interpreted as a
The MIDI device name doesn't have to be an exact match.
If ReceiveMIDI can't find the exact name that was specified, it will pick the first MIDI output port that contains the provided text, irrespective of case.

Where notes can be provided as arguments, they can also be written as note names, by default from C0 to G10 which corresponds to note numbers 0 to 127. By setting the octave for middle C, the note name range can be changed. Sharps can be added by using the '#' symbol after the note letter, and flats by using the letter 'b'.
Where notes can be provided as arguments, they can also be written as note names, by default from C-2 to G8 which corresponds to note numbers 0 to 127. By setting the octave for middle C, the note name range can be changed. Sharps can be added by using the '#' symbol after the note letter, and flats by using the letter 'b'.

## Examples

Expand Down
61 changes: 45 additions & 16 deletions Source/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ enum CommandIndex
NONE,
LIST,
DEVICE,
VIRTUAL,
TXTFILE,
DECIMAL,
HEXADECIMAL,
Expand Down Expand Up @@ -55,7 +56,8 @@ enum CommandIndex
TUNE_REQUEST
};

static const int DEFAULT_OCTAVE_MIDDLE_C = 5;
static const int DEFAULT_OCTAVE_MIDDLE_C = 3;
static const String& DEFAULT_VIRTUAL_NAME = "ReceiveMIDI";

struct ApplicationCommand
{
Expand Down Expand Up @@ -93,15 +95,16 @@ class receiveMidiApplication : public JUCEApplicationBase, public MidiInputCall
public:
receiveMidiApplication()
{
commands_.add({"dev", "device", DEVICE, 1, "name", "Set the name of the MIDI input port (REQUIRED)"});
commands_.add({"dev", "device", DEVICE, 1, "name", "Set the name of the MIDI input port"});
commands_.add({"virt", "virtual", VIRTUAL, -1, "(name)", "Use virtual MIDI port with optional name (Linux/macOS)"});
commands_.add({"list", "", LIST, 0, "", "Lists the MIDI input ports"});
commands_.add({"file", "", TXTFILE, 1, "path", "Loads commands from the specified program file"});
commands_.add({"dec", "decimal", DECIMAL, 0, "", "Interpret the next numbers as decimals by default"});
commands_.add({"hex", "hexadecimal", HEXADECIMAL, 0, "", "Interpret the next numbers as hexadecimals by default"});
commands_.add({"ch", "channel", CHANNEL, 1, "number", "Set MIDI channel for the commands (0-16), defaults to 0"});
commands_.add({"ts", "timestamp", TIMESTAMP, 0, "", "Output a timestamp for each received MIDI message"});
commands_.add({"nn", "note-numbers", NOTE_NUMBERS, 0, "", "Output notes as numbers instead of names"});
commands_.add({"omc", "octave-middle-c", OCTAVE_MIDDLE_C, 1, "number", "Set octave for middle C, defaults to 5"});
commands_.add({"omc", "octave-middle-c", OCTAVE_MIDDLE_C, 1, "number", "Set octave for middle C, defaults to 3"});
commands_.add({"voice", "", VOICE, 0, "", "Show all Channel Voice messages"});
commands_.add({"note", "", NOTE, 0, "", "Show all Note messages"});
commands_.add({"on", "note-on", NOTE_ON, -1, "(note)", "Show Note On, optionally for note (0-127)"});
Expand Down Expand Up @@ -217,14 +220,24 @@ class receiveMidiApplication : public JUCEApplicationBase, public MidiInputCall
return parameters;
}

void handleVarArgCommand()
{
if (currentCommand_.expectedOptions_ < 0)
{
executeCommand(currentCommand_);
}
}

void parseParameters(StringArray& parameters)
{
for (String param : parameters)
{
if (param == "--") continue;

ApplicationCommand* cmd = findApplicationCommand(param);
if (cmd)
{
// handle configuration commands immediately without setting up a new
// handle configuration commands immediately without setting up a new one
switch (cmd->command_)
{
case DECIMAL:
Expand All @@ -234,11 +247,7 @@ class receiveMidiApplication : public JUCEApplicationBase, public MidiInputCall
useHexadecimalsByDefault_ = true;
break;
default:
// handle variable arg commands
if (currentCommand_.expectedOptions_ < 0)
{
executeCommand(currentCommand_);
}
handleVarArgCommand();

currentCommand_ = *cmd;
break;
Expand All @@ -265,11 +274,7 @@ class receiveMidiApplication : public JUCEApplicationBase, public MidiInputCall
}
}

// handle variable arg commands
if (currentCommand_.expectedOptions_ < 0)
{
executeCommand(currentCommand_);
}
handleVarArgCommand();
}

void parseFile(File file)
Expand Down Expand Up @@ -622,6 +627,30 @@ class receiveMidiApplication : public JUCEApplicationBase, public MidiInputCall
}
break;
}
case VIRTUAL:
{
#if (JUCE_LINUX || JUCE_MAC)
String name = DEFAULT_VIRTUAL_NAME;
if (cmd.opts_.size())
{
name = cmd.opts_[0];
}
midiIn_ = MidiInput::createNewDevice(name, this);
if (midiIn_ == nullptr)
{
std::cerr << "Couldn't create virtual MIDI input port \"" << name << "\"" << std::endl;
}
else
{
midiInName_ = cmd.opts_[0];
fullMidiInName_.clear();
midiIn_->start();
}
#else
std::cerr << "Virtual MIDI input ports are not supported on Windows" << std::endl;
#endif
break;
}
case TXTFILE:
{
String path(cmd.opts_[0]);
Expand Down Expand Up @@ -687,7 +716,7 @@ class receiveMidiApplication : public JUCEApplicationBase, public MidiInputCall
note += 1;
}

note += (value.getTrailingIntValue() + DEFAULT_OCTAVE_MIDDLE_C - octaveMiddleC_) * 12;
note += (value.getTrailingIntValue() + 5 - octaveMiddleC_) * 12;

return (uint8)limit7Bit(note);
}
Expand Down Expand Up @@ -783,7 +812,7 @@ class receiveMidiApplication : public JUCEApplicationBase, public MidiInputCall
<< "first MIDI output port that contains the provided text, irrespective of case." << std::endl;
std::cout << std::endl;
std::cout << "Where notes can be provided as arguments, they can also be written as note" << std::endl
<< "names, by default from C0 to G10 which corresponds to note numbers 0 to 127." << std::endl
<< "names, by default from C-2 to G8 which corresponds to note numbers 0 to 127." << std::endl
<< "By setting the octave for middle C, the note name range can be changed. " << std::endl
<< "Sharps can be added by using the '#' symbol after the note letter, and flats" << std::endl
<< "by using the letter 'b'. " << std::endl;
Expand Down

0 comments on commit d90c2b3

Please sign in to comment.