diff --git a/index.html b/index.html
index f67fa6f..5c4e15d 100644
--- a/index.html
+++ b/index.html
@@ -261,6 +261,18 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AppSettings.ts b/src/AppSettings.ts
index 97f414c..c40c628 100644
--- a/src/AppSettings.ts
+++ b/src/AppSettings.ts
@@ -45,8 +45,10 @@ export interface Settings {
* @param time_position - Whether or not to show time position
* @param tips - Whether or not to show tips
* @param send_clock - Whether or not to send midi clock
+ * @param midi_channels_scripts - Whether midi input channels fires scripts
* @param midi_clock_input - The name of the midi clock input
* @param midi_clock_ppqn - The pulses per quarter note for midi clock
+ * @param default_midi_input - The default midi input for incoming messages
*/
vimMode: boolean;
theme: string;
@@ -59,8 +61,10 @@ export interface Settings {
load_demo_songs: boolean;
tips: boolean;
send_clock: boolean;
+ midi_channels_scripts: boolean;
midi_clock_input: string|undefined;
midi_clock_ppqn: number;
+ default_midi_input: string|undefined;
}
export const template_universe = {
@@ -118,9 +122,10 @@ export class AppSettings {
* @param time_position - Whether or not to show time position
* @param tips - Whether or not to show tips
* @param send_clock - Whether or not to send midi clock
+ * @param midi_channels_scripts - Whether midi input channels fires scripts
* @param midi_clock_input - The name of the midi clock input
* @param midi_clock_ppqn - The pulses per quarter note for midi clock
-
+ * @param default_midi_input - The default midi input for incoming messages
*/
public vimMode: boolean = false;
@@ -133,7 +138,9 @@ export class AppSettings {
public time_position: boolean = true;
public tips: boolean = true;
public send_clock: boolean = false;
+ public midi_channels_scripts: boolean = true;
public midi_clock_input: string|undefined = undefined;
+ public default_midi_input: string|undefined = undefined;
public midi_clock_ppqn: number = 24;
public load_demo_songs: boolean = true;
@@ -154,8 +161,10 @@ export class AppSettings {
this.time_position = settingsFromStorage.time_position;
this.tips = settingsFromStorage.tips;
this.send_clock = settingsFromStorage.send_clock;
+ this.midi_channels_scripts = settingsFromStorage.midi_channels_scripts;
this.midi_clock_input = settingsFromStorage.midi_clock_input;
this.midi_clock_ppqn = settingsFromStorage.midi_clock_ppqn || 24;
+ this.default_midi_input = settingsFromStorage.default_midi_input;
this.load_demo_songs = settingsFromStorage.load_demo_songs;
} else {
this.universes = template_universes;
@@ -181,8 +190,10 @@ export class AppSettings {
time_position: this.time_position,
tips: this.tips,
send_clock: this.send_clock,
+ midi_channels_scripts: this.midi_channels_scripts,
midi_clock_input: this.midi_clock_input,
midi_clock_ppqn: this.midi_clock_ppqn,
+ default_midi_input: this.default_midi_input,
load_demo_songs: this.load_demo_songs,
};
}
@@ -206,8 +217,10 @@ export class AppSettings {
this.time_position = settings.time_position;
this.tips = settings.tips;
this.send_clock = settings.send_clock;
+ this.midi_channels_scripts = settings.midi_channels_scripts;
this.midi_clock_input = settings.midi_clock_input;
this.midi_clock_ppqn = settings.midi_clock_ppqn;
+ this.default_midi_input = settings.default_midi_input;
this.load_demo_songs = settings.load_demo_songs;
localStorage.setItem("topos", JSON.stringify(this.data));
}
diff --git a/src/IO/MidiConnection.ts b/src/IO/MidiConnection.ts
index 977e440..a7fec62 100644
--- a/src/IO/MidiConnection.ts
+++ b/src/IO/MidiConnection.ts
@@ -146,45 +146,76 @@ export class MidiConnection {
* Updates the MIDI clock input select element with the available MIDI inputs.
*/
if(this.midiInputs.length > 0) {
- const select = document.getElementById("midi-clock-input") as HTMLSelectElement;
- select.innerHTML = "";
+ const midiClockSelect = document.getElementById("midi-clock-input") as HTMLSelectElement;
+ const midiInputSelect = document.getElementById("default-midi-input") as HTMLSelectElement;
+
+ midiClockSelect.innerHTML = "";
+ midiInputSelect.innerHTML = "";
+
// Defaults to internal clock
const defaultOption = document.createElement("option");
defaultOption.value = "-1";
defaultOption.text = "Internal";
- select.appendChild(defaultOption);
- // Add MIDI inputs to clock select input
+ midiClockSelect.appendChild(defaultOption);
+
+ // Add MIDI inputs to clock select input and default midi input
this.midiInputs.forEach((input, index) => {
const option = document.createElement("option");
option.value = index.toString();
option.text = input.name || index.toString();
- select.appendChild(option);
+ midiClockSelect.appendChild(option);
+ midiInputSelect.appendChild(option.cloneNode(true));
});
+
if(this.settings.midi_clock_input) {
const clockMidiInputIndex = this.getMidiInputIndex(this.settings.midi_clock_input);
- select.value = clockMidiInputIndex.toString();
+ midiClockSelect.value = clockMidiInputIndex.toString();
if(clockMidiInputIndex > 0) {
this.midiClockInput = this.midiInputs[clockMidiInputIndex];
this.registerMidiClockListener();
}
} else {
- select.value = "-1";
+ midiClockSelect.value = "-1";
}
- // Add listener
- select.addEventListener("change", (event) => {
+
+ if(this.settings.default_midi_input) {
+ const defaultMidiInputIndex = this.getMidiInputIndex(this.settings.default_midi_input);
+ midiInputSelect.value = defaultMidiInputIndex.toString();
+ if(defaultMidiInputIndex > 0) {
+ this.currentInputIndex = defaultMidiInputIndex;
+ this.registerMidiInputListener();
+ }
+ } else {
+ midiInputSelect.value = "";
+ }
+
+ // Add midi clock listener
+ midiClockSelect.addEventListener("change", (event) => {
const value = (event.target as HTMLSelectElement).value;
if(value === "-1") {
if(this.midiClockInput) this.midiClockInput.onmidimessage = null;
this.midiClockInput = undefined;
this.settings.midi_clock_input = undefined;
} else {
- this.currentInputIndex = parseInt(value);
+ const clockInputIndex = parseInt(value);
if(this.midiClockInput) this.midiClockInput.onmidimessage = null;
- this.midiClockInput = this.midiInputs[this.currentInputIndex];
+ this.midiClockInput = this.midiInputs[clockInputIndex];
this.registerMidiClockListener();
this.settings.midi_clock_input = this.midiClockInput.name || undefined;
}
});
+
+ // Add mini input listener
+ midiInputSelect.addEventListener("change", (event) => {
+ const value = (event.target as HTMLSelectElement).value;
+ if(value) {
+ this.unregisterMidiInputListener();
+ this.currentInputIndex = parseInt(value);
+ this.registerMidiInputListener();
+ this.settings.default_midi_input = this.midiInputs[this.currentInputIndex].name || undefined;
+ }
+ });
+
}
}
@@ -221,6 +252,45 @@ export class MidiConnection {
}
}
+ public registerMidiInputListener(): void {
+ /**
+ * Register midi input listener and store last value as global parameter named channel_{number}
+ */
+ if(this.currentInputIndex !== undefined) {
+ const input = this.midiInputs[this.currentInputIndex];
+ if(input) {
+ input.onmidimessage = (event: Event) => {
+ const message = event as MIDIMessageEvent;
+
+ // List of all note_on messages from channels 1-16
+ const all_note_ons = [0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D,0x9E, 0x9F];
+ // If message is one of note ons
+ if(all_note_ons.indexOf(message.data[0]) !== -1) {
+ const channel = all_note_ons.indexOf(message.data[0])+1;
+ const note = message.data[1];
+ const velocity = message.data[2];
+ this.api.variable(`channel_${channel}_note`, note);
+ this.api.variable(`channel_${channel}_velocity`, velocity);
+ if(this.settings.midi_channels_scripts) this.api.script(channel);
+ }
+ }
+ }
+ }
+ }
+
+ public unregisterMidiInputListener(): void {
+ /**
+ * Unregister midi input listener
+ */
+ if(this.currentInputIndex !== undefined) {
+ const input = this.midiInputs[this.currentInputIndex];
+ if(input) {
+ input.onmidimessage = null;
+ }
+ }
+ }
+
+
public onMidiClock(timestamp: number): void {
/**
* Called when a MIDI clock message is received.
diff --git a/src/main.ts b/src/main.ts
index 8a60818..629eb9a 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -212,6 +212,10 @@ export class Editor {
"send-midi-clock"
) as HTMLInputElement;
+ midi_channels_scripts: HTMLInputElement = document.getElementById(
+ "midi-channels-scripts"
+ ) as HTMLInputElement;
+
midi_clock_ppqn: HTMLSelectElement = document.getElementById(
"midi-clock-ppqn-input"
) as HTMLSelectElement;
@@ -262,6 +266,7 @@ export class Editor {
this.time_position_checkbox.checked = this.settings.time_position;
this.tips_checkbox.checked = this.settings.tips;
this.midi_clock_checkbox.checked = this.settings.send_clock;
+ this.midi_channels_scripts.checked = this.settings.midi_channels_scripts;
this.midi_clock_ppqn.value = this.settings.midi_clock_ppqn.toString();
if (!this.settings.time_position) {
document.getElementById("timeviewer")!.classList.add("hidden");
@@ -605,6 +610,7 @@ export class Editor {
this.time_position_checkbox.checked = this.settings.time_position;
this.tips_checkbox.checked = this.settings.tips;
this.midi_clock_checkbox.checked = this.settings.send_clock;
+ this.midi_channels_scripts.checked = this.settings.midi_channels_scripts;
this.midi_clock_ppqn.value = this.settings.midi_clock_ppqn.toString();
this.load_demo_songs.checked = this.settings.load_demo_songs;
@@ -707,6 +713,11 @@ export class Editor {
this.settings.send_clock = checked;
});
+ this.midi_channels_scripts.addEventListener("change", () => {
+ let checked = this.midi_channels_scripts.checked ? true : false;
+ this.settings.midi_channels_scripts = checked;
+ });
+
this.midi_clock_ppqn.addEventListener("change", () => {
let value = parseInt(this.midi_clock_ppqn.value);
this.settings.midi_clock_ppqn = value;