Skip to content

Commit

Permalink
Incomplete fix for reentrant TimingObject update event
Browse files Browse the repository at this point in the history
  • Loading branch information
infojunkie committed Aug 1, 2024
1 parent 97fd294 commit 78559ec
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 71 deletions.
65 changes: 30 additions & 35 deletions dist/musicxml-player.esm.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*!
* musicxml-player v0.17.0
* musicxml-player v0.17.1
* (c) Karim Ratib <[email protected]> (https://github.com/infojunkie)
* Released under the GPL-3.0-only License.
*/
Expand Down Expand Up @@ -12547,7 +12547,7 @@ const timingObjectConstructor = createTimingObjectConstructor(createCalculateTim
// @todo Expose an isSupported flag which checks for performance.now() support.

var name = "musicxml-player";
var version = "0.17.0";
var version = "0.17.1";
var description = "A simple JavaScript component that loads and plays MusicXML files in the browser using Web Audio and Web MIDI.";
var main = "dist/musicxml-player.esm.js";
var type = "module";
Expand Down Expand Up @@ -12695,8 +12695,9 @@ class Player {
}
});
}
//private _timingObjectUpdating: boolean;
constructor(_options, _sheet, _parseResult, _musicXml) {
var _a, _b, _c, _d, _e;
var _a, _b, _c, _d, _e, _f;
this._options = _options;
this._sheet = _sheet;
this._parseResult = _parseResult;
Expand Down Expand Up @@ -12763,10 +12764,10 @@ class Player {
});
this._observer.observe(this._sheet);
// Create the TimingObject.
this._timingObject = new timingObjectConstructor({ velocity: 1, position: 0 }, 0, this._options.converter.timemap.last().timestamp +
this._timingObject = new timingObjectConstructor({ velocity: (_f = this._options.velocity) !== null && _f !== void 0 ? _f : 1, position: 0 }, 0, this._options.converter.timemap.last().timestamp +
this._options.converter.timemap.last().duration);
this._timingObjectListener = (event) => this._handleTimingObjectChange(event);
this._timingObjectUpdating = false;
//this._timingObjectUpdating = false;
this._timingObject.addEventListener('change', this._timingObjectListener);
}
/**
Expand Down Expand Up @@ -12937,9 +12938,7 @@ class Player {
}
_play() {
return __awaiter(this, void 0, void 0, function* () {
var _a, _b;
const synchronizeMidi = () => {
var _a;
if (this._midiPlayer.state !== PlayerState.Playing)
return;
// Lookup the current measure number by binary-searching the timemap.
Expand All @@ -12957,21 +12956,19 @@ class Player {
// Update the cursors and listeners.
const entry = this._options.converter.timemap[index >= 0 ? index : Math.max(0, -index - 2)];
this._options.renderer.moveTo(entry.measure, entry.timestamp, Math.max(0, timestamp - entry.timestamp), entry.duration);
this._timingObjectUpdate({
position: timestamp,
velocity: (_a = this._options.velocity) !== null && _a !== void 0 ? _a : 1,
});
this._timingObjectUpdate({ position: timestamp });
// Schedule next cursor movement.
requestAnimationFrame(synchronizeMidi);
};
// Schedule first cursor movement.
requestAnimationFrame(synchronizeMidi);
// Activate the MIDI player.
const { velocity } = this.timingObject.query();
if (this._midiPlayer.state === PlayerState.Paused) {
yield this._midiPlayer.resume((_a = this._options.velocity) !== null && _a !== void 0 ? _a : 1);
yield this._midiPlayer.resume(velocity);
}
else {
yield this._midiPlayer.play((_b = this._options.velocity) !== null && _b !== void 0 ? _b : 1);
yield this._midiPlayer.play(velocity);
}
// Repeat if needed.
if (this._midiPlayer.state === PlayerState.Stopped) {
Expand All @@ -12983,32 +12980,30 @@ class Player {
}
_timingObjectUpdate(newVector) {
return __awaiter(this, void 0, void 0, function* () {
this._timingObjectUpdating = true;
//this._timingObjectUpdating = true;
this._timingObject.update(newVector);
});
}
_handleTimingObjectChange(_event) {
// Don't handle our internally-generated events.
if (this._timingObjectUpdating) {
this._timingObjectUpdating = false;
return;
}
// Handle externally-generated events.
const { velocity, position } = this.timingObject.query();
if (velocity === 0) {
if (position === 0) {
this.rewind();
}
else {
this.pause();
}
}
else {
if (this._midiPlayer.state !== PlayerState.Stopped) {
this._midiPlayer.velocity = velocity;
this._midiPlayer.position = position;
}
}
// // Don't handle our internally-generated events.
// if (this._timingObjectUpdating) {
// this._timingObjectUpdating = false;
// return;
// }
// // Handle externally-generated events.
// const { velocity, position } = this.timingObject.query();
// if (velocity === 0) {
// if (position === 0) {
// this.rewind();
// } else {
// this.pause();
// }
// } else {
// if (this._midiPlayer.state !== PlayerState.Stopped) {
// this._midiPlayer.velocity = velocity;
// this._midiPlayer.position = position;
// }
// }
}
static _unroll(musicXml) {
return __awaiter(this, void 0, void 0, function* () {
Expand Down
2 changes: 1 addition & 1 deletion dist/musicxml-player.esm.js.map

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion dist/types/Player.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ export declare class Player implements IMidiOutput {
private _repeatCounter;
private _timingObject;
private _timingObjectListener;
private _timingObjectUpdating;
private constructor();
/**
* Destroy the instance by freeing all resources and disconnecting observers.
Expand Down
2 changes: 1 addition & 1 deletion dist/types/Player.d.ts.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "musicxml-player",
"version": "0.17.0",
"version": "0.17.1",
"description": "A simple JavaScript component that loads and plays MusicXML files in the browser using Web Audio and Web MIDI.",
"main": "dist/musicxml-player.esm.js",
"type": "module",
Expand Down
57 changes: 27 additions & 30 deletions src/Player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ export class Player implements IMidiOutput {
private _repeatCounter: number;
private _timingObject: ITimingObject;
private _timingObjectListener: EventListener;
private _timingObjectUpdating: boolean;
//private _timingObjectUpdating: boolean;

private constructor(
private _options: PlayerOptions,
Expand Down Expand Up @@ -210,14 +210,14 @@ export class Player implements IMidiOutput {

// Create the TimingObject.
this._timingObject = new TimingObject(
{ velocity: 1, position: 0 },
{ velocity: this._options.velocity ?? 1, position: 0 },
0,
this._options.converter.timemap.last().timestamp +
this._options.converter.timemap.last().duration,
);
this._timingObjectListener = (event) =>
this._handleTimingObjectChange(event);
this._timingObjectUpdating = false;
//this._timingObjectUpdating = false;
this._timingObject.addEventListener('change', this._timingObjectListener);
}

Expand Down Expand Up @@ -436,10 +436,7 @@ export class Player implements IMidiOutput {
Math.max(0, timestamp - entry.timestamp),
entry.duration,
);
this._timingObjectUpdate({
position: timestamp,
velocity: this._options.velocity ?? 1,
});
this._timingObjectUpdate({ position: timestamp });

// Schedule next cursor movement.
requestAnimationFrame(synchronizeMidi);
Expand All @@ -449,10 +446,11 @@ export class Player implements IMidiOutput {
requestAnimationFrame(synchronizeMidi);

// Activate the MIDI player.
const { velocity } = this.timingObject.query();
if (this._midiPlayer.state === PlayerState.Paused) {
await this._midiPlayer.resume(this._options.velocity ?? 1);
await this._midiPlayer.resume(velocity);
} else {
await this._midiPlayer.play(this._options.velocity ?? 1);
await this._midiPlayer.play(velocity);
}

// Repeat if needed.
Expand All @@ -466,31 +464,30 @@ export class Player implements IMidiOutput {
private async _timingObjectUpdate(
newVector: TTimingStateVectorUpdate,
): Promise<void> {
this._timingObjectUpdating = true;
//this._timingObjectUpdating = true;
this._timingObject.update(newVector);
}

private _handleTimingObjectChange(_event: Event) {
// Don't handle our internally-generated events.
if (this._timingObjectUpdating) {
this._timingObjectUpdating = false;
return;
}

// Handle externally-generated events.
const { velocity, position } = this.timingObject.query();
if (velocity === 0) {
if (position === 0) {
this.rewind();
} else {
this.pause();
}
} else {
if (this._midiPlayer.state !== PlayerState.Stopped) {
this._midiPlayer.velocity = velocity;
this._midiPlayer.position = position;
}
}
// // Don't handle our internally-generated events.
// if (this._timingObjectUpdating) {
// this._timingObjectUpdating = false;
// return;
// }
// // Handle externally-generated events.
// const { velocity, position } = this.timingObject.query();
// if (velocity === 0) {
// if (position === 0) {
// this.rewind();
// } else {
// this.pause();
// }
// } else {
// if (this._midiPlayer.state !== PlayerState.Stopped) {
// this._midiPlayer.velocity = velocity;
// this._midiPlayer.position = position;
// }
// }
}

private static async _unroll(musicXml: string): Promise<string> {
Expand Down

0 comments on commit 78559ec

Please sign in to comment.