From d262a5841ee04994572ab9cc3513bba81b9d8698 Mon Sep 17 00:00:00 2001 From: Danielku15 Date: Mon, 7 Mar 2022 20:56:31 +0100 Subject: [PATCH 1/3] Added event for changed playback ranges. --- src/AlphaTabApiBase.ts | 13 +++++++++++++ .../javascript/AlphaSynthWebWorker.ts | 9 +++++++++ .../javascript/AlphaSynthWebWorkerApi.ts | 10 ++++++++++ src/synth/AlphaSynth.ts | 5 +++++ src/synth/IAlphaSynth.ts | 6 ++++++ src/synth/PlaybackRangeChangedEventArgs.ts | 19 +++++++++++++++++++ 6 files changed, 62 insertions(+) create mode 100644 src/synth/PlaybackRangeChangedEventArgs.ts diff --git a/src/AlphaTabApiBase.ts b/src/AlphaTabApiBase.ts index 891e58dc3..69e738c00 100644 --- a/src/AlphaTabApiBase.ts +++ b/src/AlphaTabApiBase.ts @@ -42,6 +42,7 @@ import { AlphaTabError, AlphaTabErrorType } from '@src/AlphaTabError'; import { Note } from '@src/model/Note'; import { MidiEventType } from '@src/midi/MidiEvent'; import { MidiEventsPlayedEventArgs } from '@src/synth/MidiEventsPlayedEventArgs'; +import { PlaybackRangeChangedEventArgs } from './synth/PlaybackRangeChangedEventArgs'; class SelectionInfo { public beat: Beat; @@ -579,6 +580,7 @@ export class AlphaTabApiBase { this.player.stateChanged.on(this.onPlayerStateChanged.bind(this)); this.player.positionChanged.on(this.onPlayerPositionChanged.bind(this)); this.player.midiEventsPlayed.on(this.onMidiEventsPlayed.bind(this)); + this.player.playbackRangeChanged.on(this.onPlaybackRangeChanged.bind(this)); this.player.finished.on(this.onPlayerFinished.bind(this)); if (this.settings.player.enableCursor) { this.setupCursors(); @@ -775,6 +777,7 @@ export class AlphaTabApiBase { this._playerState = PlayerState.Paused; // we need to update our position caches if we render a tablature this.renderer.postRenderFinished.on(() => { + debugger; this.cursorUpdateTick(this._previousTick, false, this._previousTick > 10); }); if (this.player) { @@ -1413,4 +1416,14 @@ export class AlphaTabApiBase { (this.midiEventsPlayed as EventEmitterOfT).trigger(e); this.uiFacade.triggerEvent(this.container, 'midiEventsPlayed', e); } + + public playbackRangeChanged: IEventEmitterOfT = + new EventEmitterOfT(); + private onPlaybackRangeChanged(e: PlaybackRangeChangedEventArgs): void { + if (this._isDestroyed) { + return; + } + (this.playbackRangeChanged as EventEmitterOfT).trigger(e); + this.uiFacade.triggerEvent(this.container, 'playbackRangeChanged', e); + } } diff --git a/src/platform/javascript/AlphaSynthWebWorker.ts b/src/platform/javascript/AlphaSynthWebWorker.ts index 14de21e1a..db5794baa 100644 --- a/src/platform/javascript/AlphaSynthWebWorker.ts +++ b/src/platform/javascript/AlphaSynthWebWorker.ts @@ -7,6 +7,7 @@ import { IWorkerScope } from '@src/platform/javascript/IWorkerScope'; import { Logger } from '@src/Logger'; import { Environment } from '@src/Environment'; import { MidiEventsPlayedEventArgs } from '@src/synth/MidiEventsPlayedEventArgs'; +import { PlaybackRangeChangedEventArgs } from '@src/synth/PlaybackRangeChangedEventArgs'; /** * This class implements a HTML5 WebWorker based version of alphaSynth @@ -32,6 +33,7 @@ export class AlphaSynthWebWorker { this._player.midiLoadFailed.on(this.onMidiLoadFailed.bind(this)); this._player.readyForPlayback.on(this.onReadyForPlayback.bind(this)); this._player.midiEventsPlayed.on(this.onMidiEventsPlayed.bind(this)); + this._player.playbackRangeChanged.on(this.onPlaybackRangeChanged.bind(this)); this._main.postMessage({ cmd: 'alphaSynth.ready' }); @@ -213,4 +215,11 @@ export class AlphaSynthWebWorker { events: args.events.map(JsonConverter.midiEventToJsObject) }); } + + public onPlaybackRangeChanged(args: PlaybackRangeChangedEventArgs): void { + this._main.postMessage({ + cmd: 'alphaSynth.playbackRangeChanged', + playbackRange: args.playbackRange + }); + } } diff --git a/src/platform/javascript/AlphaSynthWebWorkerApi.ts b/src/platform/javascript/AlphaSynthWebWorkerApi.ts index 83f066856..cc9247bf9 100644 --- a/src/platform/javascript/AlphaSynthWebWorkerApi.ts +++ b/src/platform/javascript/AlphaSynthWebWorkerApi.ts @@ -16,6 +16,7 @@ import { FileLoadError } from '@src/FileLoadError'; import { MidiEventsPlayedEventArgs } from '@src/synth/MidiEventsPlayedEventArgs'; import { MidiEventType } from '@src/midi/MidiEvent'; import { Environment } from '@src/Environment'; +import { PlaybackRangeChangedEventArgs } from '@src/synth/PlaybackRangeChangedEventArgs'; /** * a WebWorker based alphaSynth which uses the given player as output. @@ -375,6 +376,12 @@ export class AlphaSynthWebWorkerApi implements IAlphaSynth { new PlayerStateChangedEventArgs(data.state, data.stopped) ); break; + case 'alphaSynth.playbackRangeChanged': + this._playbackRange = (data as PlaybackRangeChangedEventArgs).playbackRange; + (this.playbackRangeChanged as EventEmitterOfT).trigger( + new PlaybackRangeChangedEventArgs(this._playbackRange) + ); + break; case 'alphaSynth.finished': (this.finished as EventEmitter).trigger(); break; @@ -442,6 +449,9 @@ export class AlphaSynthWebWorkerApi implements IAlphaSynth { readonly midiEventsPlayed: IEventEmitterOfT = new EventEmitterOfT< MidiEventsPlayedEventArgs >(); + readonly playbackRangeChanged: IEventEmitterOfT = new EventEmitterOfT< + PlaybackRangeChangedEventArgs + >(); // // output communication ( output -> worker ) diff --git a/src/synth/AlphaSynth.ts b/src/synth/AlphaSynth.ts index 346031736..dd2091795 100644 --- a/src/synth/AlphaSynth.ts +++ b/src/synth/AlphaSynth.ts @@ -18,6 +18,7 @@ import { SynthEvent } from '@src/synth/synthesis/SynthEvent'; import { Queue } from '@src/synth/ds/Queue'; import { MidiEventsPlayedEventArgs } from '@src/synth/MidiEventsPlayedEventArgs'; import { MidiEvent, MidiEventType } from '@src/midi/MidiEvent'; +import { PlaybackRangeChangedEventArgs } from './PlaybackRangeChangedEventArgs'; /** * This is the main synthesizer component which can be used to @@ -139,6 +140,9 @@ export class AlphaSynth implements IAlphaSynth { if (value) { this.tickPosition = value.startTick; } + (this.playbackRangeChanged as EventEmitterOfT).trigger( + new PlaybackRangeChangedEventArgs(value) + ); } public get isLooping(): boolean { @@ -459,4 +463,5 @@ export class AlphaSynth implements IAlphaSynth { readonly stateChanged: IEventEmitterOfT = new EventEmitterOfT(); readonly positionChanged: IEventEmitterOfT = new EventEmitterOfT(); readonly midiEventsPlayed: IEventEmitterOfT = new EventEmitterOfT(); + readonly playbackRangeChanged: IEventEmitterOfT = new EventEmitterOfT(); } diff --git a/src/synth/IAlphaSynth.ts b/src/synth/IAlphaSynth.ts index 4062e145a..e7a39f7a6 100644 --- a/src/synth/IAlphaSynth.ts +++ b/src/synth/IAlphaSynth.ts @@ -2,6 +2,7 @@ import { MidiFile } from '@src/midi/MidiFile'; import { PlaybackRange } from '@src/synth/PlaybackRange'; import { PlayerState } from '@src/synth/PlayerState'; import { PlayerStateChangedEventArgs } from '@src/synth/PlayerStateChangedEventArgs'; +import { PlaybackRangeChangedEventArgs } from '@src/synth/PlaybackRangeChangedEventArgs'; import { PositionChangedEventArgs } from '@src/synth/PositionChangedEventArgs'; import { IEventEmitter, IEventEmitterOfT } from '@src/EventEmitter'; import { LogLevel } from '@src/LogLevel'; @@ -204,4 +205,9 @@ export interface IAlphaSynth { * The event is fired when certain midi events were sent to the audio output device for playback. */ readonly midiEventsPlayed: IEventEmitterOfT; + + /** + * The event is fired when the playback range within the player was updated. + */ + readonly playbackRangeChanged: IEventEmitterOfT; } diff --git a/src/synth/PlaybackRangeChangedEventArgs.ts b/src/synth/PlaybackRangeChangedEventArgs.ts new file mode 100644 index 000000000..fd3e58a81 --- /dev/null +++ b/src/synth/PlaybackRangeChangedEventArgs.ts @@ -0,0 +1,19 @@ +import { PlaybackRange } from '@src/synth/PlaybackRange'; + +/** + * Represents the info when the playback range changed. + */ +export class PlaybackRangeChangedEventArgs { + /** + * The new playback range. + */ + public readonly playbackRange: PlaybackRange | null; + + /** + * Initializes a new instance of the {@link PlaybackRangeChangedEventArgs} class. + * @param range The range. + */ + public constructor(playbackRange: PlaybackRange | null) { + this.playbackRange = playbackRange; + } +} From 9764506c1682d21bc6e9ea05d059b5bfd3901584 Mon Sep 17 00:00:00 2001 From: Danielku15 Date: Mon, 7 Mar 2022 21:01:30 +0100 Subject: [PATCH 2/3] Expose new args and cleaned imports --- src/AlphaTabApiBase.ts | 2 +- src/synth/AlphaSynth.ts | 2 +- src/synth/index.ts | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/AlphaTabApiBase.ts b/src/AlphaTabApiBase.ts index 69e738c00..b47590e1c 100644 --- a/src/AlphaTabApiBase.ts +++ b/src/AlphaTabApiBase.ts @@ -42,7 +42,7 @@ import { AlphaTabError, AlphaTabErrorType } from '@src/AlphaTabError'; import { Note } from '@src/model/Note'; import { MidiEventType } from '@src/midi/MidiEvent'; import { MidiEventsPlayedEventArgs } from '@src/synth/MidiEventsPlayedEventArgs'; -import { PlaybackRangeChangedEventArgs } from './synth/PlaybackRangeChangedEventArgs'; +import { PlaybackRangeChangedEventArgs } from '@src/synth/PlaybackRangeChangedEventArgs'; class SelectionInfo { public beat: Beat; diff --git a/src/synth/AlphaSynth.ts b/src/synth/AlphaSynth.ts index dd2091795..5769b95d5 100644 --- a/src/synth/AlphaSynth.ts +++ b/src/synth/AlphaSynth.ts @@ -18,7 +18,7 @@ import { SynthEvent } from '@src/synth/synthesis/SynthEvent'; import { Queue } from '@src/synth/ds/Queue'; import { MidiEventsPlayedEventArgs } from '@src/synth/MidiEventsPlayedEventArgs'; import { MidiEvent, MidiEventType } from '@src/midi/MidiEvent'; -import { PlaybackRangeChangedEventArgs } from './PlaybackRangeChangedEventArgs'; +import { PlaybackRangeChangedEventArgs } from '@src/synth/PlaybackRangeChangedEventArgs'; /** * This is the main synthesizer component which can be used to diff --git a/src/synth/index.ts b/src/synth/index.ts index 5e8cb1fe8..842d2f213 100644 --- a/src/synth/index.ts +++ b/src/synth/index.ts @@ -2,5 +2,6 @@ export { AlphaSynth } from '@src/synth/AlphaSynth'; export { PlaybackRange } from '@src/synth/PlaybackRange'; export { PlayerState } from '@src/synth/PlayerState'; export { PlayerStateChangedEventArgs } from '@src/synth/PlayerStateChangedEventArgs'; +export { PlaybackRangeChangedEventArgs } from '@src/synth/PlaybackRangeChangedEventArgs'; export { PositionChangedEventArgs } from '@src/synth/PositionChangedEventArgs'; export { AlphaSynthWebWorkerApi } from '@src/platform/javascript/AlphaSynthWebWorkerApi'; From 4beef521d911bafcf5aa3e1ac790feae89984973 Mon Sep 17 00:00:00 2001 From: Danielku15 Date: Mon, 7 Mar 2022 21:10:14 +0100 Subject: [PATCH 3/3] Update .net and Kotlin platforms with new event --- .../AlphaTab/Platform/CSharp/AlphaSynthWorkerApiBase.cs | 7 +++++++ .../android/AndroidThreadAlphaSynthWorkerPlayer.kt | 9 +++++++++ 2 files changed, 16 insertions(+) diff --git a/src.csharp/AlphaTab/Platform/CSharp/AlphaSynthWorkerApiBase.cs b/src.csharp/AlphaTab/Platform/CSharp/AlphaSynthWorkerApiBase.cs index 5b8bc7fc2..8670d44c4 100644 --- a/src.csharp/AlphaTab/Platform/CSharp/AlphaSynthWorkerApiBase.cs +++ b/src.csharp/AlphaTab/Platform/CSharp/AlphaSynthWorkerApiBase.cs @@ -36,6 +36,7 @@ protected void Initialize() Player.MidiLoadFailed.On(OnMidiLoadFailed); Player.ReadyForPlayback.On(OnReadyForPlayback); Player.MidiEventsPlayed.On(OnMidiEventsPlayed); + Player.PlaybackRangeChanged.On(OnPlaybackRangeChanged); DispatchOnUiThread(OnReady); } @@ -186,6 +187,7 @@ public void SetChannelVolume(double channel, double volume) public IEventEmitterOfT StateChanged { get; } = new EventEmitterOfT(); public IEventEmitterOfT PositionChanged { get; } = new EventEmitterOfT(); public IEventEmitterOfT MidiEventsPlayed { get; } = new EventEmitterOfT(); + public IEventEmitterOfT PlaybackRangeChanged { get; } = new EventEmitterOfT(); protected virtual void OnReady() { @@ -236,5 +238,10 @@ protected virtual void OnPositionChanged(PositionChangedEventArgs obj) { DispatchOnUiThread(() => ((EventEmitterOfT)PositionChanged).Trigger(obj)); } + + protected virtual void OnPlaybackRangeChanged(PlaybackRangeChangedEventArgs obj) + { + DispatchOnUiThread(() => ((EventEmitterOfT)PlaybackRangeChanged).Trigger(obj)); + } } } diff --git a/src.kotlin/alphaTab/alphaTab/src/androidMain/kotlin/alphaTab/platform/android/AndroidThreadAlphaSynthWorkerPlayer.kt b/src.kotlin/alphaTab/alphaTab/src/androidMain/kotlin/alphaTab/platform/android/AndroidThreadAlphaSynthWorkerPlayer.kt index 8af94e63d..190d2bc24 100644 --- a/src.kotlin/alphaTab/alphaTab/src/androidMain/kotlin/alphaTab/platform/android/AndroidThreadAlphaSynthWorkerPlayer.kt +++ b/src.kotlin/alphaTab/alphaTab/src/androidMain/kotlin/alphaTab/platform/android/AndroidThreadAlphaSynthWorkerPlayer.kt @@ -107,6 +107,9 @@ internal class AndroidThreadAlphaSynthWorkerPlayer : IAlphaSynth, Runnable { player.midiEventsPlayed.on { _uiInvoke { onMidiEventsPlayed(it) } } + player.playbackRangeChanged.on { + _uiInvoke { onPlaybackRangeChanged(it) } + } _uiInvoke { onReady() } } @@ -253,6 +256,8 @@ internal class AndroidThreadAlphaSynthWorkerPlayer : IAlphaSynth, Runnable { EventEmitterOfT() override val midiEventsPlayed: IEventEmitterOfT = EventEmitterOfT() + override val playbackRangeChanged: IEventEmitterOfT = + EventEmitterOfT() private fun onReady() { @@ -294,4 +299,8 @@ internal class AndroidThreadAlphaSynthWorkerPlayer : IAlphaSynth, Runnable { private fun onPositionChanged(obj: PositionChangedEventArgs) { _uiInvoke { (positionChanged as EventEmitterOfT).trigger(obj) } } + + private fun onPlaybackRangeChanged(obj: PlaybackRangeChangedEventArgs) { + _uiInvoke { (playbackRangeChanged as EventEmitterOfT).trigger(obj) } + } }