Skip to content

Commit bf7b498

Browse files
committed
Default enableMidi to false and defer requesting midi access until enabled, to avoid scary warning message.
1 parent 4b10adb commit bf7b498

6 files changed

Lines changed: 46 additions & 27 deletions

File tree

editor/EditorConfig.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ export interface Preset extends BeepBoxOption {
1515
readonly settings?: any;
1616
}
1717

18-
export const isMobile: boolean = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini|android|ipad|playbook|silk/i.test(navigator.userAgent);
18+
// Instead of checking the user agent string to determine whether the device is mobile,
19+
// try checking whether the primary pointer device is "coarse" (i.e. a touchscreen).
20+
// export const isMobile: boolean = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini|android|ipad|playbook|silk/i.test(navigator.userAgent);
21+
export const isMobile: boolean = matchMedia("(pointer:coarse)").matches;
1922

2023
export function prettyNumber(value: number): string {
2124
return value.toFixed(2).replace(/\.?0*$/, "");

editor/MidiInput.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,17 @@ interface MIDIMessageEvent {
2929
const id: string = ((Math.random() * 0xffffffff) >>> 0).toString(16);
3030

3131
export class MidiInputHandler {
32+
private _triedToRegisterMidiAccess: boolean = false;
33+
3234
constructor(private _doc: SongDocument) {
33-
this.registerMidiAccessHandler();
35+
this.tryRegisteringMidiAccessHandler();
3436
}
3537

36-
private async registerMidiAccessHandler() {
38+
public async tryRegisteringMidiAccessHandler() {
3739
if (navigator.requestMIDIAccess == null) return;
40+
if (!this._doc.prefs.enableMidi) return;
41+
if (this._triedToRegisterMidiAccess) return;
42+
this._triedToRegisterMidiAccess = true;
3843

3944
try {
4045
const midiAccess = await navigator.requestMIDIAccess();

editor/Preferences.ts

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) John Nesky and contributing authors, distributed under the MIT license, see accompanying the LICENSE.md file.
22

33
import {Scale, Config} from "../synth/SynthConfig.js";
4+
import {isMobile} from "./EditorConfig.js";
45

56
export class Preferences {
67
public static readonly defaultVisibleOctaves: number = 3;
@@ -36,25 +37,25 @@ export class Preferences {
3637
}
3738

3839
public reload(): void {
39-
this.autoPlay = window.localStorage.getItem("autoPlay") == "true";
40-
this.autoFollow = window.localStorage.getItem("autoFollow") != "false";
41-
this.enableNotePreview = window.localStorage.getItem("enableNotePreview") != "false";
42-
this.showFifth = window.localStorage.getItem("showFifth") == "true";
43-
this.notesOutsideScale = window.localStorage.getItem("notesOutsideScale") == "true";
44-
this.showLetters = window.localStorage.getItem("showLetters") == "true";
45-
this.showChannels = window.localStorage.getItem("showChannels") == "true";
46-
this.showScrollBar = window.localStorage.getItem("showScrollBar") == "true";
47-
this.alwaysShowSettings = window.localStorage.getItem("alwaysShowSettings") == "true";
48-
this.instrumentCopyPaste = window.localStorage.getItem("instrumentCopyPaste") == "true";
49-
this.enableChannelMuting = window.localStorage.getItem("enableChannelMuting") == "true";
50-
this.displayBrowserUrl = window.localStorage.getItem("displayBrowserUrl") != "false";
51-
this.pressControlForShortcuts = window.localStorage.getItem("pressControlForShortcuts") == "true";
52-
this.enableMidi = window.localStorage.getItem("enableMidi") != "false";
53-
this.showRecordButton = window.localStorage.getItem("showRecordButton") == "true";
54-
this.snapRecordedNotesToRhythm = window.localStorage.getItem("snapRecordedNotesToRhythm") == "true";
55-
this.ignorePerformedNotesNotInScale = window.localStorage.getItem("ignorePerformedNotesNotInScale") == "true";
56-
this.metronomeCountIn = window.localStorage.getItem("metronomeCountIn") != "false";
57-
this.metronomeWhileRecording = window.localStorage.getItem("metronomeWhileRecording") != "false";
40+
this.autoPlay = this._loadBoolean("autoPlay", false);
41+
this.autoFollow = this._loadBoolean("autoFollow", true);
42+
this.enableNotePreview = this._loadBoolean("enableNotePreview", true);
43+
this.showFifth = this._loadBoolean("showFifth", false);
44+
this.notesOutsideScale = this._loadBoolean("notesOutsideScale", false);
45+
this.showLetters = this._loadBoolean("showLetters", false);
46+
this.showChannels = this._loadBoolean("showChannels", false);
47+
this.showScrollBar = this._loadBoolean("showScrollBar", false);
48+
this.alwaysShowSettings = this._loadBoolean("alwaysShowSettings", false);
49+
this.instrumentCopyPaste = this._loadBoolean("instrumentCopyPaste", false);
50+
this.enableChannelMuting = this._loadBoolean("enableChannelMuting", false);
51+
this.displayBrowserUrl = this._loadBoolean("displayBrowserUrl", true);
52+
this.pressControlForShortcuts = this._loadBoolean("pressControlForShortcuts", false);
53+
this.enableMidi = this._loadBoolean("enableMidi", !isMobile);
54+
this.showRecordButton = this._loadBoolean("showRecordButton", false);
55+
this.snapRecordedNotesToRhythm = this._loadBoolean("snapRecordedNotesToRhythm", false);
56+
this.ignorePerformedNotesNotInScale = this._loadBoolean("ignorePerformedNotesNotInScale", false);
57+
this.metronomeCountIn = this._loadBoolean("metronomeCountIn", true);
58+
this.metronomeWhileRecording = this._loadBoolean("metronomeWhileRecording", true);
5859
this.keyboardLayout = window.localStorage.getItem("keyboardLayout") || "wickiHayden";
5960
this.layout = window.localStorage.getItem("layout") || "small";
6061
this.colorTheme = window.localStorage.getItem("colorTheme") || "dark classic";
@@ -68,7 +69,7 @@ export class Preferences {
6869
}
6970

7071
if (window.localStorage.getItem("fullScreen") != null) {
71-
if (window.localStorage.getItem("fullScreen") == "true") this.layout = "long";
72+
if (this._loadBoolean("fullScreen", false)) this.layout = "long";
7273
window.localStorage.removeItem("fullScreen");
7374
}
7475
}
@@ -88,7 +89,7 @@ export class Preferences {
8889
window.localStorage.setItem("instrumentCopyPaste", this.instrumentCopyPaste ? "true" : "false");
8990
window.localStorage.setItem("displayBrowserUrl", this.displayBrowserUrl ? "true" : "false");
9091
window.localStorage.setItem("pressControlForShortcuts", this.pressControlForShortcuts ? "true" : "false");
91-
window.localStorage.setItem("enableMidi", this.enableMidi ? "true" : "false");
92+
window.localStorage.setItem("enableMidi", false);
9293
window.localStorage.setItem("showRecordButton", this.showRecordButton ? "true" : "false");
9394
window.localStorage.setItem("snapRecordedNotesToRhythm", this.snapRecordedNotesToRhythm ? "true" : "false");
9495
window.localStorage.setItem("ignorePerformedNotesNotInScale", this.ignorePerformedNotesNotInScale ? "true" : "false");
@@ -100,4 +101,10 @@ export class Preferences {
100101
window.localStorage.setItem("volume", String(this.volume));
101102
window.localStorage.setItem("visibleOctaves", String(this.visibleOctaves));
102103
}
104+
105+
private _loadBoolean(name: string, defaultToTrue: boolean) {
106+
return defaultToTrue
107+
? window.localStorage.getItem(name) != "false"
108+
: window.localStorage.getItem(name) == "true";
109+
}
103110
}

editor/RecordingSetupPrompt.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ export class RecordingSetupPrompt implements Prompt {
6969
"Count-in 1 bar of metronome before recording:",
7070
this._metronomeCountIn,
7171
),
72-
p("If you have a ", a({href: "https://caniuse.com/midi", target: "_blank"}, "compatible browser"), " on a device connected to a MIDI keyboard, you can use it to perform notes in BeepBox! (Or you could buy ", a({href: "https://imitone.com/", target: "_blank"}, "Imitone"), " or ", a({href: "https://vochlea.com/", target: "_blank"}, "Dubler"), " to hum notes into a microphone while wearing headphones!)"),
72+
p("If you have a ", a({href: "https://caniuse.com/midi", target: "_blank"}, "compatible browser"), " on a device connected to a MIDI keyboard, enable this option to use it to perform notes in BeepBox! (Or you could buy ", a({href: "https://imitone.com/", target: "_blank"}, "Imitone"), " or ", a({href: "https://vochlea.com/", target: "_blank"}, "Dubler"), " to hum notes into a microphone while wearing headphones!)"),
7373
label({style: "display: flex; flex-direction: row; align-items: center; height: 2em; justify-content: flex-end;"},
7474
"Enable MIDI performance:",
7575
this._enableMidi,
@@ -130,6 +130,8 @@ export class RecordingSetupPrompt implements Prompt {
130130
this._doc.prefs.metronomeCountIn = this._metronomeCountIn.checked;
131131
this._doc.prefs.metronomeWhileRecording = this._metronomeWhileRecording.checked;
132132
this._doc.prefs.save();
133+
// enableMidi may have changed, try registering a MIDI access handler again.
134+
this._doc.midiInputHandler.tryRegisteringMidiAccessHandler();
133135
this._close();
134136
}
135137

editor/SongDocument.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {Layout} from "./Layout.js";
77
import {Pattern, Channel, Song, Synth} from "../synth/synth.js";
88
import {SongRecovery, generateUid, errorAlert} from "./SongRecovery.js";
99
import {SongPerformance} from "./SongPerformance.js";
10+
import {MidiInputHandler} from "./MidiInput.js";
1011
import {Selection} from "./Selection.js";
1112
import {Preferences} from "./Preferences.js";
1213
import {Change} from "./Change.js";
@@ -28,6 +29,7 @@ export class SongDocument {
2829
public song: Song;
2930
public synth: Synth;
3031
public performance: SongPerformance;
32+
public midiInputHandler: MidiInputHandler;
3133
public readonly notifier: ChangeNotifier = new ChangeNotifier(() => this._validateDocState());
3234
public readonly selection: Selection = new Selection(this);
3335
public readonly prefs: Preferences = new Preferences();
@@ -117,6 +119,7 @@ export class SongDocument {
117119

118120
this._validateDocState();
119121
this.performance = new SongPerformance(this);
122+
this.midiInputHandler = new MidiInputHandler(this);
120123
}
121124

122125
public toggleDisplayBrowserUrl() {

editor/SongEditor.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import {SpectrumEditor} from "./SpectrumEditor.js";
2424
import {HarmonicsEditor} from "./HarmonicsEditor.js";
2525
import {BarScrollBar} from "./BarScrollBar.js";
2626
import {OctaveScrollBar} from "./OctaveScrollBar.js";
27-
import {MidiInputHandler} from "./MidiInput.js";
2827
import {KeyboardLayout} from "./KeyboardLayout.js";
2928
import {Piano} from "./Piano.js";
3029
import {BeatsPerBarPrompt} from "./BeatsPerBarPrompt.js";
@@ -511,7 +510,7 @@ export class SongEditor {
511510

512511
constructor(beepboxEditorContainer: HTMLElement) {
513512
this.doc.notifier.watch(this.whenUpdated);
514-
new MidiInputHandler(this.doc);
513+
515514
window.addEventListener("resize", this.whenUpdated);
516515
window.requestAnimationFrame(this.updatePlayButton);
517516

0 commit comments

Comments
 (0)