Skip to content

Commit

Permalink
adds Trigger functionality back
Browse files Browse the repository at this point in the history
  • Loading branch information
josephdadams committed Aug 18, 2023
1 parent 996de44 commit f1ca364
Show file tree
Hide file tree
Showing 10 changed files with 2,197 additions and 117 deletions.
37 changes: 37 additions & 0 deletions api.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const socketio = require('socket.io');
const util = require('./util.js');
const config = require('./config.js');
const notifications = require('./notifications.js');
const path = require('path');

const package_json = require('./package.json');
const VERSION = package_json.version;
Expand All @@ -23,6 +24,8 @@ class API {

server.use(express.json()); //parse json in body

server.use(express.static(path.join(__dirname, 'static')));

server.get('/', function (req, res) {
res.sendFile('index.html', { root: __dirname });
});
Expand Down Expand Up @@ -62,6 +65,10 @@ class API {
});
});

server.get('/', function (req, res) {
res.redirect('/index.html');
});

server.use(function (req, res) {
res.status(404).send({error: true, url: req.originalUrl + ' not found.'});
});
Expand Down Expand Up @@ -93,6 +100,36 @@ class API {
});
}
});

socket.on('getMidiInputs', function() {
socket.emit('midi_inputs', util.getMIDIInputs());
});

socket.on('getTriggers', function() {
socket.emit('triggers', util.getTriggers());
});

socket.on('getTriggers_download', function() {
socket.emit('triggers_download', util.getTriggers());
});

socket.on('trigger_add', function(triggerObj) {
if (triggerObj) {
util.addTrigger(triggerObj);
}
});

socket.on('trigger_update', function(triggerObj) {
if (triggerObj) {
util.updateTrigger(triggerObj);
}
});

socket.on('trigger_delete', function(triggerObj) {
if (triggerObj) {
util.deleteTrigger(triggerObj);
}
});
});

try {
Expand Down
114 changes: 1 addition & 113 deletions api.md
Original file line number Diff line number Diff line change
Expand Up @@ -247,8 +247,6 @@ Emitted whenever there is an error. Contains the error message as a string.
All values for `channel` are zero-based. (e.g., Channel of `1` should be sent as `0`.)


# The following only applies to midi-relay v2.x and lower:

## Receiving MIDI Input Messages
The midi-relay server can also listen for incoming MIDI messages and act on them.

Expand All @@ -265,117 +263,7 @@ The following incoming MIDI Messages are currently supported:
* Pitch Bend / Pitch Wheel
* SysEx (System Exclusive)

### Opening a Port
Make a POST request to `/openport` with a JSON object:
```javascript
{
midiport: 'MIDI Port Name'
}
```

### Closing a Port
Make a POST request to `/closeport` with a JSON object:
```javascript
{
midiport: 'MIDI Port Name'
}
```

### Getting MIDI Input Port Names
You can make a GET request to `/midi_inputs` if you need the names of available MIDI input ports on the server. If a port is already opened, that object in the returned array will have a property of `opened: true`.

### MIDI Input Triggers
In order for midi-relay to act on an incoming MIDI message, a trigger must exist that matches the conditions of the incoming message on the specified MIDI port.

You can make a GET request to `/triggers` to see a list of currently stored triggers.

### Adding a Trigger
Make a POST request with JSON object data to `/addtrigger` with the following options:

Each trigger must specify a `midiport` using the name of the port as a string.

A `midicommand` property must also be included:
* `noteon` (Note On)
* Must include properties `channel`, `note`, and `velocity` in the trigger. You can use an asterisk `"*"` as a wildcard to match any `channel`, or `velocity` value. A `note` value must always be specific.
* `noteoff` (Note Off)
* Same as `noteon`. Any `noteon` or `noteoff` message with a `velocity` value of `0`, it will be treated as a `noteoff` message when processed.
* `aftertouch` (Polyphonic Aftertouch)
* Must include properties `channel`, `note`, and `value` in the trigger. An asterisk `"*"` can be used as a wildcard for `channel` and/or `value`.
* `cc` (Control Change)
* Must include properties `channel`, `controller`, and `value` in the trigger. An asterisk `"*"` can be used as a wildcard for `channel` and/or `value`.
* `pc` (Program Change)
* Must include properties `channel` and `value` in the trigger. An asterisk `"*"` can be used as a wildcard for `channel` and/or `value`.
* `pressure` (Channel Pressure / Aftertouch)
* Must include properties `channel` and `value` in the trigger. An asterisk `"*"` can be used as a wildcard for `channel` and/or `value`.
* `pitchbend` (Pitch Bend / Pitch Wheel)
* Must include properties `channel` and `value` in the trigger. An asterisk `"*"` can be used as a wildcard for `channel` and/or `value`.
* `sysex` (System Exclusive)
* Must include `message` property in the trigger as a string with values separated by spaces or commas. All values will be converted to decimal.

In addition to specifying a `midicommand` and related command properties, an `actiontype` must also be specified.

The following action types are currently supported:
* `http` (HTTP GET or POST)
* Include a object property of `url` to send the URL.
* Include `jsondata` with the stringified JSON to send as HTTP POST. Otherwise, it will send as HTTP GET.
* `applescript` (AppleScript, MacOS only)
* Results of script or any errors will appear in the console/terminal.
* `shellscript` (Shell Script)
* Output of shell scripts will appear in the console/terminal.

You can also include a `description` field to store information related to the trigger, what it does, etc.

#### Example Trigger Object
```javascript
{
midiport: 'IAC Driver Bus 1',
midicommand: 'noteon',
note: 73,
channel: 1,
velocity: 100,
actiontype: 'http',
url: 'http://127.0.0.1/test',
description: 'description of the trigger'
}
```

### Deleting a Trigger
To delete an existing trigger, make a GET request to `/deletetrigger/[trigger-id]`.

The trigger ID is autogenerated by the system and viewable in the `midi-triggers.json` file.

## API Responses
The API will respond with JSON messages for each action received.

* `invalid-midi-port`: The MIDI port you specified is invalid or is no longer available. Call `/refresh` to get the latest list of available ports.
* `invalid-midi-command`: The MIDI command you sent is invalid or not implemented.
* `midiin-port-cannot-be-opened`: The MIDI Input port cannot be opened due to an internal error.
* `midiin-port-opened`: The MIDI Input port is now open.
* `midiin-port-already-opened`: The MIDI Input port was already open.
* `midiin-port-cannot-be-closed`: The MIDI Input port cannot be closed due to an internal error.
* `midiin-port-closed`: The MIDI Input port is now closed.
* `ports-refreshed-successfully`: MIDI Input/Output ports were refreshed and updated successfully.
* `noteon-sent-successfully`: The Note On message was sent successfully.
* `noteoff-sent-successfully`: The Note Off message was sent successfully.
* `aftertouch-sent-successfully`: The Polyphonic Aftertouch message was sent successfully.
* `cc-sent-successfully`: The Control Change message was sent successfully.
* `pc-sent-successfully`: The Program Change message was sent successfully.
* `pressure-sent-successfully`: The Channel Pressure / Aftertouch message was sent successfully.
* `pitchbend-sent-successfully`: The Pitch Bend message was sent successfully.
* `msc-sent-successfully`: The MSC (MIDI Show Control) message was sent successfully.
* `sysex-sent-successfully`: The SysEx MIDI message was sent successfully.
* `sysex-invalid`: The provided message was not a valid SysEx message.
* `could-not-open-midi-out`: The specified MIDI-Out port could not be opened. The message was not sent.
* `invalid-action-type`: The action type specified in the Add Trigger API was not valid.
* `trigger-added`: The trigger was added successfully.
* `trigger-added-midiin-port-cannot-be-opened`: The trigger was added, but the MIDI In port could not be automatically opened.
* `trigger-edited`: The trigger was edited successfully.
* `trigger-edited-midiin-port-cannot-be-opened`: The trigger was edited, but the MIDI In port could not be automatically opened.
* `trigger-deleted`: The trigger was deleted successfully.
* `trigger-not-found`: The Trigger could not be found due to an invalid/incorrect Trigger ID, or it was already deleted.
* `error`: An unexpected error occurred. Check the `error` property for more information.

The console/terminal output running the server process is also verbose and will report on the current status of the server.

## MDNS/Bonjour Discovery
The midi-relay server will broadcast itself on the network as `midi-relay` on the listening port. It will also monitor for other midi-relay servers available on the network. This list can be accessed by making a GET request to `/hosts`.
You can make add/edit/remove triggers by using the web interface. Navigate to `http://127.0.0.1:4000/` (replace `127.0.0.1` with the IP of the computer running midi-relay if it is not the same computer you are on.)
3 changes: 2 additions & 1 deletion config.js

Large diffs are not rendered by default.

7 changes: 6 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ global.MIDI_OUTPUTS = [];

global.IncomingMIDIRelayTypes = ['noteon', 'noteoff', 'aftertouch', 'cc', 'pc', 'pressure', 'pitchbend', 'msc', 'sysex'];

global.MIDIRelaysLog = []; //global array of MIDI messages and the datetime they were sent

global.MDNS_HOSTS = [];

global.sendControlStatus = function() {
Expand Down Expand Up @@ -79,9 +81,12 @@ const createMainWindow = async () => {
});

global.win.on('ready-to-show', () => {
if (config.get('showLicense')) {
if (config.get('showLicense') == true) {
global.win.show();
}
else {
global.win.hide();
}
});

global.win.on('closed', () => {
Expand Down
Loading

0 comments on commit f1ca364

Please sign in to comment.