From e2751603809087150960f0bbea66d9656690d866 Mon Sep 17 00:00:00 2001 From: Philipp Otto Date: Sun, 29 Oct 2017 12:58:05 +0100 Subject: [PATCH] make midi usage optional and fix some midi detection issues --- app/scripts/AppFreezer.js | 1 + app/scripts/services/bar_generator.js | 5 +- app/scripts/views/claviature_view.js | 10 +++- app/scripts/views/collapsable_container.js | 2 +- app/scripts/views/pitch_reading_view.js | 58 +++++++++++++++------- app/scripts/views/pitch_settings_view.js | 50 ++++++++++++------- app/scripts/views/rhythm_reading_view.js | 2 +- 7 files changed, 85 insertions(+), 43 deletions(-) diff --git a/app/scripts/AppFreezer.js b/app/scripts/AppFreezer.js index e4b7e70..2248f64 100644 --- a/app/scripts/AppFreezer.js +++ b/app/scripts/AppFreezer.js @@ -15,6 +15,7 @@ let defaultSettings = { }, keySignature: [7, 7], useAccidentals: false, + tryToUseMidi: true, midi: { inputs: Freezer.createLeaf([]), activeInputIndex: 0, diff --git a/app/scripts/services/bar_generator.js b/app/scripts/services/bar_generator.js index 37b2ab6..b23f05e 100644 --- a/app/scripts/services/bar_generator.js +++ b/app/scripts/services/bar_generator.js @@ -148,10 +148,7 @@ export default { return ["treble", "bass"].map(clef => _.random.apply(_, settings.chordSizeRanges[clef])); }, - generateBars: function(settings, level) { - const isMidiAvailable = settings.midi.inputs.get().length > 0; - const onePerTime = !isMidiAvailable; - + generateBars: function(settings, level, onePerTime) { const [trebleNotes, bassNotes] = _.unzip( _.range(0, options.chordsPerBar).map(() => { const generatePossibleNotes = clef => { diff --git a/app/scripts/views/claviature_view.js b/app/scripts/views/claviature_view.js index 40668b1..c56b1d7 100644 --- a/app/scripts/views/claviature_view.js +++ b/app/scripts/views/claviature_view.js @@ -114,9 +114,15 @@ export default class ClaviatureView extends Component { ["a#", "A# B♭", "black"], ["b", "B", "white"], ].map(args => this.renderKey.apply(this, args)); + return ( -
-
    {keys}
+
+
+
    {keys}
+
+ Click on the keys of the claviature or use your keyboard to hit notes!
); } diff --git a/app/scripts/views/collapsable_container.js b/app/scripts/views/collapsable_container.js index e215942..b1b3613 100644 --- a/app/scripts/views/collapsable_container.js +++ b/app/scripts/views/collapsable_container.js @@ -28,7 +28,7 @@ export default class CollapsableContainer extends Component { }), ]).join(" "); - const maxHeight = this.props.maxHeight || 300; + const maxHeight = this.props.maxHeight || 500; const style = collapsed ? {} : { maxHeight }; const children = collapsed && this.props.freeze && this.oldChildren ? this.oldChildren : this.props.children; diff --git a/app/scripts/views/pitch_reading_view.js b/app/scripts/views/pitch_reading_view.js index 22156bb..39d76cf 100644 --- a/app/scripts/views/pitch_reading_view.js +++ b/app/scripts/views/pitch_reading_view.js @@ -37,8 +37,8 @@ export default class PitchReadingView extends Component { this.midiService = new MidiService({ successCallback: this.onSuccess.bind(this), failureCallback: this.onFailure.bind(this), - errorCallback: this.onError.bind(this), - errorResolveCallback: this.onErrorResolve.bind(this), + errorCallback: this.onMidiError.bind(this), + errorResolveCallback: this.onMidiErrorResolve.bind(this), }); this.startDate = new Date(); this.midiService.setDesiredKeys(this.getAllCurrentKeys(), this.state.currentKeySignature); @@ -106,7 +106,15 @@ export default class PitchReadingView extends Component { generateNewBars(settings) { const levelIndex = LevelService.getLevelOfUser(this.props.statisticService.getAllEvents()) + 1; const level = LevelService.getLevelByIndex(levelIndex); - return BarGenerator.generateBars(settings, settings.useAutomaticDifficulty ? level : null); + + const { isMidiAvailable } = this.getMidiInfo(); + const onePerTime = !isMidiAvailable; + + return BarGenerator.generateBars( + settings, + settings.useAutomaticDifficulty ? level : null, + onePerTime, + ); } generateNewBarState() { @@ -120,7 +128,7 @@ export default class PitchReadingView extends Component { constructor(props, context) { super(props, context); this.state = { - errorMessage: null, + midiErrorMessage: null, running: false, ...this.generateNewBarState(), }; @@ -132,16 +140,30 @@ export default class PitchReadingView extends Component { this.startDate = new Date(); } + getMidiInfo() { + const tryToUseMidi = this.props.settings.tryToUseMidi; + const isMidiAvailable = this.props.settings.midi.inputs.get().length > 0; + const useMidi = tryToUseMidi && isMidiAvailable; + const noMidiErrors = !this.state ? true : this.state.midiErrorMessage == null; + + return { + tryToUseMidi, + isMidiAvailable, + useMidi, + noMidiErrors, + }; + } + render() { const claviatureContainerClasses = classNames({ "content-box": true, "claviature-container": true, }); - const isMidiAvailable = this.props.settings.midi.inputs.get().length > 0; - const noErrors = this.state.errorMessage !== null; + const { tryToUseMidi, isMidiAvailable, useMidi, noMidiErrors } = this.getMidiInfo(); + const miniClaviature = - isMidiAvailable && noErrors ? null : ( + useMidi && noMidiErrors ? null : ( -

Welcome to this pitch training!

+

Welcome to pitch training!

{"When you hit Start, notes will be displayed in the stave above. "} - {isMidiAvailable + {useMidi ? "Since we found a connected piano, you can use it to play the notes. " : "Just use the mini claviature below to play the notes. "} {"Don't worry about the rhythm or speed for now."}

- {isMidiAvailable ? null : midiSetUpText} + {tryToUseMidi && !isMidiAvailable ? midiSetUpText : null}
); @@ -194,6 +216,8 @@ export default class PitchReadingView extends Component { bass: [], }; + const hideMidiError = !tryToUseMidi || noMidiErrors; + return (
@@ -217,16 +241,16 @@ export default class PitchReadingView extends Component {
- +
{miniClaviature}
-

{this.state.errorMessage}

+

{this.state.midiErrorMessage}

@@ -257,13 +281,13 @@ export default class PitchReadingView extends Component { this.midiService.setDesiredKeys(this.getAllCurrentKeys(), this.state.currentKeySignature); } - onError(msg) { + onMidiError(msg) { console.error.apply(console, arguments); - this.setState({ errorMessage: msg }); + this.setState({ midiErrorMessage: msg }); } - onErrorResolve() { - this.setState({ errorMessage: null }); + onMidiErrorResolve() { + this.setState({ midiErrorMessage: null }); } getAllCurrentKeys() { diff --git a/app/scripts/views/pitch_settings_view.js b/app/scripts/views/pitch_settings_view.js index 4d968ff..f0f2a8b 100644 --- a/app/scripts/views/pitch_settings_view.js +++ b/app/scripts/views/pitch_settings_view.js @@ -57,25 +57,39 @@ export default class PitchSettingsView extends Component { const midiSettings = this.props.settings.midi; const midiInputs = midiSettings.inputs.get(); const isMidiAvailable = midiInputs.length > 0; + const tryToUseMidi = this.props.settings.tryToUseMidi; const deviceSelector = !isMidiAvailable ? null : ( - - - +
+ + + + + + +
); const useAutomaticDifficulty = this.props.settings.useAutomaticDifficulty; diff --git a/app/scripts/views/rhythm_reading_view.js b/app/scripts/views/rhythm_reading_view.js index 699fea7..20fd63a 100644 --- a/app/scripts/views/rhythm_reading_view.js +++ b/app/scripts/views/rhythm_reading_view.js @@ -214,7 +214,7 @@ export default class RhythmReadingView extends Component { render() { const welcomeText = ( -

Welcome to this rhythm training!

+

Welcome to rhythm training!

When you start the training, we will count in for 4 beats and afterwards you can tap the given rhythm (either use your ‘space’ button or your touchscreen). Make sure