Store Midi clock stuff to localstorage

This commit is contained in:
2023-10-04 00:20:50 +03:00
parent c6b65c799f
commit 327bfc5086
4 changed files with 45 additions and 16 deletions

View File

@ -60,7 +60,7 @@ export class UserAPI {
load: samples;
constructor(public app: Editor) {
this.MidiConnection = new MidiConnection(this);
this.MidiConnection = new MidiConnection(this, app.settings);
}
_loadUniverseFromInterface = (universe: string) => {

View File

@ -45,6 +45,8 @@ 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_clock_input - The name of the midi clock input
* @param midi_clock_ppqn - The pulses per quarter note for midi clock
*/
vimMode: boolean;
theme: string;
@ -56,6 +58,8 @@ export interface Settings {
time_position: boolean;
tips: boolean;
send_clock: boolean;
midi_clock_input: string|undefined;
midi_clock_ppqn: number;
}
export const template_universe = {
@ -113,6 +117,8 @@ 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_clock_input - The name of the midi clock input
* @param midi_clock_ppqn - The pulses per quarter note for midi clock
*/
@ -126,6 +132,8 @@ export class AppSettings {
public time_position: boolean = true;
public tips: boolean = true;
public send_clock: boolean = false;
public midi_clock_input: string|undefined = undefined;
public midi_clock_ppqn: number = 24;
constructor() {
const settingsFromStorage = JSON.parse(
@ -144,6 +152,8 @@ export class AppSettings {
this.time_position = settingsFromStorage.time_position;
this.tips = settingsFromStorage.tips;
this.send_clock = settingsFromStorage.send_clock;
this.midi_clock_input = settingsFromStorage.midi_clock_input;
this.midi_clock_ppqn = settingsFromStorage.midi_clock_ppqn || 24;
} else {
this.universes = template_universes;
}
@ -168,6 +178,8 @@ export class AppSettings {
time_position: this.time_position,
tips: this.tips,
send_clock: this.send_clock,
midi_clock_input: this.midi_clock_input,
midi_clock_ppqn: this.midi_clock_ppqn,
};
}
@ -190,6 +202,8 @@ export class AppSettings {
this.time_position = settings.time_position;
this.tips = settings.tips;
this.send_clock = settings.send_clock;
this.midi_clock_input = settings.midi_clock_input;
this.midi_clock_ppqn = settings.midi_clock_ppqn;
localStorage.setItem("topos", JSON.stringify(this.data));
}
}

View File

@ -1,4 +1,5 @@
import { UserAPI } from "../API";
import { AppSettings } from "../AppSettings";
export class MidiConnection {
/**
@ -12,6 +13,7 @@ export class MidiConnection {
*/
private api: UserAPI;
private settings: AppSettings;
private midiAccess: MIDIAccess | null = null;
public midiOutputs: MIDIOutput[] = [];
public midiInputs: MIDIInput[] = [];
@ -28,13 +30,13 @@ export class MidiConnection {
private clockBuffer: number[] = [];
private deltaBuffer: number[] = [];
private clockBufferLength = 24;
private clockPPQN = 24;
private clockTicks = 0;
private clockErrorCount = 0;
private skipOnError = 0;
constructor(api: UserAPI) {
constructor(api: UserAPI, settings: AppSettings) {
this.api = api;
this.settings = settings;
this.lastBPM = api.bpm();
this.roundedBPM = this.lastBPM;
this.initializeMidiAccess();
@ -58,7 +60,6 @@ export class MidiConnection {
console.warn("No MIDI inputs available.");
} else {
this.updateMidiClockSelect();
this.clockPPQNSelect();
}
} catch (error) {
console.error("Failed to initialize MIDI:", error);
@ -156,34 +157,37 @@ export class MidiConnection {
this.midiInputs.forEach((input, index) => {
const option = document.createElement("option");
option.value = index.toString();
option.text = input.name || "No name input";
option.text = input.name || index.toString();
select.appendChild(option);
});
select.value = this.currentInputIndex ? this.currentInputIndex.toString() : "-1";
if(this.settings.midi_clock_input) {
const clockMidiInputIndex = this.getMidiInputIndex(this.settings.midi_clock_input);
select.value = clockMidiInputIndex.toString();
if(clockMidiInputIndex > 0) {
this.midiClockInput = this.midiInputs[clockMidiInputIndex];
this.registerMidiClockListener();
}
} else {
select.value = "-1";
}
// Add listener
select.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);
if(this.midiClockInput) this.midiClockInput.onmidimessage = null;
this.midiClockInput = this.midiInputs[this.currentInputIndex];
this.registerMidiClockListener();
this.settings.midi_clock_input = this.midiClockInput.name || undefined;
}
});
}
}
clockPPQNSelect(): void {
const select = document.getElementById("midi-clock-ppqn-input") as HTMLSelectElement;
select.addEventListener("change", (event) => {
const value = (event.target as HTMLSelectElement).value;
this.clockPPQN = parseInt(value);
});
}
public registerMidiClockListener(): void {
/**
* Registers a listener for MIDI clock messages on the currently selected MIDI input.
@ -241,12 +245,12 @@ export class MidiConnection {
this.clockErrorCount = 0;
/* I dont know why this happens. But when it does, deltas for the following messages are off.
So skipping ~ quarted of clock resolution usually helps */
this.skipOnError = this.clockPPQN/4;
this.skipOnError = this.settings.midi_clock_ppqn/4;
timestamp = 0; // timestamp 0 == lastTimestamp 0
} else {
this.midiClockDelta = timestamp - this.lastTimestamp;
this.lastBPM = 60 * (1000 / this.midiClockDelta / 24);
this.lastBPM = 60 * (1000 / this.midiClockDelta / this.settings.midi_clock_ppqn);
this.clockBuffer.push(this.lastBPM);
if(this.clockBuffer.length>this.clockBufferLength) this.clockBuffer.shift();

View File

@ -197,6 +197,10 @@ export class Editor {
"send-midi-clock"
) as HTMLInputElement;
midi_clock_ppqn: HTMLSelectElement = document.getElementById(
"midi-clock-ppqn-input"
) as HTMLSelectElement;
// Editor mode selection
normal_mode_button: HTMLButtonElement = document.getElementById(
"normal-mode"
@ -246,6 +250,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_clock_ppqn.value = this.settings.midi_clock_ppqn.toString();
if (!this.settings.time_position) {
document.getElementById("timeviewer")!.classList.add("hidden");
}
@ -565,6 +570,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_clock_ppqn.value = this.settings.midi_clock_ppqn.toString();
if (this.settings.vimMode) {
let vim = document.getElementById("vim-mode-radio") as HTMLInputElement;
@ -665,6 +671,11 @@ export class Editor {
this.settings.send_clock = checked;
});
this.midi_clock_ppqn.addEventListener("change", () => {
let value = parseInt(this.midi_clock_ppqn.value);
this.settings.midi_clock_ppqn = value;
});
this.vim_mode_button.addEventListener("click", () => {
this.settings.vimMode = true;
this.view.dispatch({