@coderline/alphatab 1.6.0-alpha.1409 → 1.6.0-alpha.1416

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/alphaTab.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * alphaTab v1.6.0-alpha.1409 (develop, build 1409)
2
+ * alphaTab v1.6.0-alpha.1416 (develop, build 1416)
3
3
  *
4
4
  * Copyright © 2025, Daniel Kuschny and Contributors, All rights reserved.
5
5
  *
@@ -1419,7 +1419,7 @@
1419
1419
  this.barOccurence = 0;
1420
1420
  /**
1421
1421
  * The modified tempo at which the cursor should move (aka. the tempo played within the external audio track).
1422
- * This information is used together with the {@link originalTempo} to calculate how much faster/slower the
1422
+ * This information is used together with normal tempo changes to calculate how much faster/slower the
1423
1423
  * cursor playback is performed to align with the audio track.
1424
1424
  */
1425
1425
  this.modifiedTempo = 0;
@@ -3377,18 +3377,26 @@
3377
3377
  const lookup = new Map();
3378
3378
  const score = tracks[0].score;
3379
3379
  let currentIndex = startIndex;
3380
+ let tempo = score.tempo;
3380
3381
  while (currentIndex <= endIndexInclusive) {
3381
3382
  const currentGroupStartIndex = currentIndex;
3382
3383
  let currentGroup = null;
3383
3384
  while (currentIndex <= endIndexInclusive) {
3384
3385
  const masterBar = score.masterBars[currentIndex];
3386
+ let hasTempoChange = false;
3387
+ for (const a of masterBar.tempoAutomations) {
3388
+ if (a.value !== tempo) {
3389
+ hasTempoChange = true;
3390
+ }
3391
+ tempo = a.value;
3392
+ }
3385
3393
  // check if masterbar breaks multibar rests, it must be fully empty with no annotations
3386
3394
  if (masterBar.alternateEndings ||
3387
3395
  (masterBar.isRepeatStart && masterBar.index !== currentGroupStartIndex) ||
3388
3396
  masterBar.isFreeTime ||
3389
3397
  masterBar.isAnacrusis ||
3390
3398
  masterBar.section !== null ||
3391
- (masterBar.index !== currentGroupStartIndex && masterBar.tempoAutomations.length > 0) ||
3399
+ (masterBar.index !== currentGroupStartIndex && hasTempoChange) ||
3392
3400
  (masterBar.fermata !== null && masterBar.fermata.size > 0) ||
3393
3401
  (masterBar.directions !== null && masterBar.directions.size > 0)) {
3394
3402
  break;
@@ -20221,7 +20229,11 @@
20221
20229
  for (const c of element.childElements()) {
20222
20230
  switch (c.localName) {
20223
20231
  case 'direction-type':
20224
- directionTypes.push(c.firstElement);
20232
+ // See https://github.com/CoderLine/alphaTab/issues/2102
20233
+ const type = c.firstElement;
20234
+ if (type) {
20235
+ directionTypes.push(type);
20236
+ }
20225
20237
  break;
20226
20238
  case 'offset':
20227
20239
  offset = Number.parseFloat(c.innerText);
@@ -38602,6 +38614,93 @@
38602
38614
  }
38603
38615
  }
38604
38616
 
38617
+ /**
38618
+ * A {@link IScoreRenderer} implementation wrapping and underling other {@link IScoreRenderer}
38619
+ * allowing dynamic changing of the underlying instance without loosing aspects like the
38620
+ * event listeners.
38621
+ */
38622
+ class ScoreRendererWrapper {
38623
+ constructor() {
38624
+ this._width = 0;
38625
+ this._score = null;
38626
+ this._trackIndexes = null;
38627
+ this.preRender = new EventEmitterOfT();
38628
+ this.renderFinished = new EventEmitterOfT();
38629
+ this.partialRenderFinished = new EventEmitterOfT();
38630
+ this.partialLayoutFinished = new EventEmitterOfT();
38631
+ this.postRenderFinished = new EventEmitter();
38632
+ this.error = new EventEmitterOfT();
38633
+ }
38634
+ get instance() {
38635
+ return this._instance;
38636
+ }
38637
+ set instance(value) {
38638
+ this._instance = value;
38639
+ // unregister all events from previous instance
38640
+ const unregister = this._instanceEventUnregister;
38641
+ if (unregister) {
38642
+ for (const e of unregister) {
38643
+ e();
38644
+ }
38645
+ }
38646
+ if (value) {
38647
+ // regsiter to events of new player and forward them to existing listeners
38648
+ const newUnregister = [];
38649
+ newUnregister.push(value.preRender.on(v => this.preRender.trigger(v)));
38650
+ newUnregister.push(value.renderFinished.on(v => this.renderFinished.trigger(v)));
38651
+ newUnregister.push(value.partialRenderFinished.on(v => this.partialRenderFinished.trigger(v)));
38652
+ newUnregister.push(value.partialLayoutFinished.on(v => this.partialLayoutFinished.trigger(v)));
38653
+ newUnregister.push(value.postRenderFinished.on(() => this.postRenderFinished.trigger()));
38654
+ newUnregister.push(value.error.on(v => this.error.trigger(v)));
38655
+ this._instanceEventUnregister = newUnregister;
38656
+ if (this._settings) {
38657
+ value.updateSettings(this._settings);
38658
+ }
38659
+ value.width = this._width;
38660
+ if (this._score !== null) {
38661
+ value.renderScore(this._score, this._trackIndexes);
38662
+ }
38663
+ }
38664
+ else {
38665
+ this._instanceEventUnregister = undefined;
38666
+ }
38667
+ }
38668
+ get boundsLookup() {
38669
+ return this._instance ? this._instance.boundsLookup : null;
38670
+ }
38671
+ get width() {
38672
+ return this._instance ? this._instance.width : 0;
38673
+ }
38674
+ set width(value) {
38675
+ this._width = value;
38676
+ if (this._instance) {
38677
+ this._instance.width = value;
38678
+ }
38679
+ }
38680
+ render() {
38681
+ this._instance?.render();
38682
+ }
38683
+ resizeRender() {
38684
+ this._instance?.resizeRender();
38685
+ }
38686
+ renderScore(score, trackIndexes) {
38687
+ this._score = score;
38688
+ this._trackIndexes = trackIndexes;
38689
+ this._instance?.renderScore(score, trackIndexes);
38690
+ }
38691
+ renderResult(resultId) {
38692
+ this._instance?.renderResult(resultId);
38693
+ }
38694
+ updateSettings(settings) {
38695
+ this._settings = settings;
38696
+ this._instance?.updateSettings(settings);
38697
+ }
38698
+ destroy() {
38699
+ this._instance?.destroy();
38700
+ this._instance = undefined;
38701
+ }
38702
+ }
38703
+
38605
38704
  class SelectionInfo {
38606
38705
  constructor(beat) {
38607
38706
  this.bounds = null;
@@ -38616,11 +38715,27 @@
38616
38715
  */
38617
38716
  class AlphaTabApiBase {
38618
38717
  /**
38619
- * The actual player mode which is currently active (e.g. allows determining whether a backing track or the synthesizer is active).
38718
+ * The actual player mode which is currently active.
38719
+ * @remarks
38720
+ * Allows determining whether a backing track or the synthesizer is active in case automatic detection is enabled.
38721
+ * @category Properties - Player
38722
+ * @since 1.6.0
38620
38723
  */
38621
38724
  get actualPlayerMode() {
38622
38725
  return this._actualPlayerMode;
38623
38726
  }
38727
+ /**
38728
+ * The score renderer used for rendering the music sheet.
38729
+ * @remarks
38730
+ * This is the low-level API responsible for the actual rendering engine.
38731
+ * Gets access to the underling {@link IScoreRenderer} that is used for the rendering.
38732
+ *
38733
+ * @category Properties - Core
38734
+ * @since 0.9.4
38735
+ */
38736
+ get renderer() {
38737
+ return this._renderer;
38738
+ }
38624
38739
  /**
38625
38740
  * The score holding all information about the song being rendered
38626
38741
  * @category Properties - Core
@@ -38699,6 +38814,7 @@
38699
38814
  this._previousTick = 0;
38700
38815
  this._currentBeat = null;
38701
38816
  this._currentBeatBounds = null;
38817
+ this._isInitialBeatCursorUpdate = true;
38702
38818
  this._previousStateForCursor = PlayerState.Paused;
38703
38819
  this._previousCursorCache = null;
38704
38820
  this._lastScroll = 0;
@@ -39357,7 +39473,40 @@
39357
39473
  */
39358
39474
  this.midiLoaded = new EventEmitterOfT();
39359
39475
  /**
39360
- * @internal
39476
+ * This event is fired when a settings update was requested.
39477
+ *
39478
+ * @eventProperty
39479
+ * @category Events - Core
39480
+ * @since 1.6.0
39481
+ *
39482
+ * @example
39483
+ * JavaScript
39484
+ * ```js
39485
+ * const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
39486
+ * api.settingsUpdated.on(() => {
39487
+ * updateSettingsUI(api.settings);
39488
+ * });
39489
+ * ```
39490
+ *
39491
+ * @example
39492
+ * C#
39493
+ * ```cs
39494
+ * var api = new AlphaTabApi<MyControl>(...);
39495
+ * api.SettingsUpdated.On(() =>
39496
+ * {
39497
+ * UpdateSettingsUI(api.settings);
39498
+ * });
39499
+ * ```
39500
+ *
39501
+ * @example
39502
+ * Android
39503
+ * ```kotlin
39504
+ * val api = AlphaTabApi<MyControl>(...)
39505
+ * api.SettingsUpdated.on {
39506
+ * updateSettingsUI(api.settings)
39507
+ * }
39508
+ * ```
39509
+ *
39361
39510
  */
39362
39511
  this.settingsUpdated = new EventEmitter();
39363
39512
  this.uiFacade = uiFacade;
@@ -39371,46 +39520,46 @@
39371
39520
  Environment.printEnvironmentInfo(false);
39372
39521
  this.canvasElement = uiFacade.createCanvasElement();
39373
39522
  this.container.appendChild(this.canvasElement);
39523
+ this._renderer = new ScoreRendererWrapper();
39374
39524
  if (this.settings.core.useWorkers &&
39375
39525
  this.uiFacade.areWorkersSupported &&
39376
39526
  Environment.getRenderEngineFactory(this.settings.core.engine).supportsWorkers) {
39377
- this.renderer = this.uiFacade.createWorkerRenderer();
39527
+ this._renderer.instance = this.uiFacade.createWorkerRenderer();
39378
39528
  }
39379
39529
  else {
39380
- this.renderer = new ScoreRenderer(this.settings);
39530
+ this._renderer.instance = new ScoreRenderer(this.settings);
39381
39531
  }
39382
39532
  this.container.resize.on(Environment.throttle(() => {
39383
39533
  if (this._isDestroyed) {
39384
39534
  return;
39385
39535
  }
39386
- if (this.container.width !== this.renderer.width) {
39536
+ if (this.container.width !== this._renderer.width) {
39387
39537
  this.triggerResize();
39388
39538
  }
39389
39539
  }, uiFacade.resizeThrottle));
39390
39540
  const initialResizeEventInfo = new ResizeEventArgs();
39391
- initialResizeEventInfo.oldWidth = this.renderer.width;
39541
+ initialResizeEventInfo.oldWidth = this._renderer.width;
39392
39542
  initialResizeEventInfo.newWidth = this.container.width | 0;
39393
39543
  initialResizeEventInfo.settings = this.settings;
39394
39544
  this.onResize(initialResizeEventInfo);
39395
- this.renderer.preRender.on(this.onRenderStarted.bind(this));
39396
- this.renderer.renderFinished.on(renderingResult => {
39545
+ this._renderer.preRender.on(this.onRenderStarted.bind(this));
39546
+ this._renderer.renderFinished.on(renderingResult => {
39397
39547
  this.onRenderFinished(renderingResult);
39398
39548
  });
39399
- this.renderer.postRenderFinished.on(() => {
39549
+ this._renderer.postRenderFinished.on(() => {
39400
39550
  const duration = Date.now() - this._startTime;
39401
39551
  Logger.debug('rendering', `Rendering completed in ${duration}ms`);
39402
39552
  this.onPostRenderFinished();
39403
39553
  });
39404
- this.renderer.preRender.on(_ => {
39554
+ this._renderer.preRender.on(_ => {
39405
39555
  this._startTime = Date.now();
39406
39556
  });
39407
- this.renderer.partialLayoutFinished.on(this.appendRenderResult.bind(this));
39408
- this.renderer.partialRenderFinished.on(this.updateRenderResult.bind(this));
39409
- this.renderer.renderFinished.on(r => {
39410
- this.appendRenderResult(r);
39411
- this.appendRenderResult(null); // marks last element
39557
+ this._renderer.partialLayoutFinished.on(r => this.appendRenderResult(r, false));
39558
+ this._renderer.partialRenderFinished.on(this.updateRenderResult.bind(this));
39559
+ this._renderer.renderFinished.on(r => {
39560
+ this.appendRenderResult(r, true);
39412
39561
  });
39413
- this.renderer.error.on(this.onError.bind(this));
39562
+ this._renderer.error.on(this.onError.bind(this));
39414
39563
  this.setupPlayerWrapper();
39415
39564
  if (this.settings.player.playerMode !== exports.PlayerMode.Disabled) {
39416
39565
  this.setupOrDestroyPlayer();
@@ -39485,7 +39634,7 @@
39485
39634
  this._isDestroyed = true;
39486
39635
  this._player.destroy();
39487
39636
  this.uiFacade.destroy();
39488
- this.renderer.destroy();
39637
+ this._renderer.destroy();
39489
39638
  }
39490
39639
  /**
39491
39640
  * Applies any changes that were done to the settings object.
@@ -39530,12 +39679,30 @@
39530
39679
  if (score) {
39531
39680
  ModelUtils.applyPitchOffsets(this.settings, score);
39532
39681
  }
39533
- this.renderer.updateSettings(this.settings);
39534
- if (this.setupOrDestroyPlayer()) {
39535
- this.loadMidiForScore();
39536
- }
39682
+ this.updateRenderer();
39683
+ this._renderer.updateSettings(this.settings);
39684
+ this.setupOrDestroyPlayer();
39537
39685
  this.onSettingsUpdated();
39538
39686
  }
39687
+ updateRenderer() {
39688
+ const renderer = this._renderer;
39689
+ if (this.settings.core.useWorkers &&
39690
+ this.uiFacade.areWorkersSupported &&
39691
+ Environment.getRenderEngineFactory(this.settings.core.engine).supportsWorkers) {
39692
+ // switch from non-worker to worker renderer
39693
+ if (renderer.instance instanceof ScoreRenderer) {
39694
+ renderer.destroy();
39695
+ renderer.instance = this.uiFacade.createWorkerRenderer();
39696
+ }
39697
+ }
39698
+ else {
39699
+ // switch from worker to non-worker renderer
39700
+ if (!(renderer.instance instanceof ScoreRenderer)) {
39701
+ renderer.destroy();
39702
+ renderer.instance = new ScoreRenderer(this.settings);
39703
+ }
39704
+ }
39705
+ }
39539
39706
  /**
39540
39707
  * Initiates a load of the score using the given data.
39541
39708
  * @returns true if the data object is supported and a load was initiated, otherwise false
@@ -39730,30 +39897,33 @@
39730
39897
  }
39731
39898
  else {
39732
39899
  const resizeEventInfo = new ResizeEventArgs();
39733
- resizeEventInfo.oldWidth = this.renderer.width;
39900
+ resizeEventInfo.oldWidth = this._renderer.width;
39734
39901
  resizeEventInfo.newWidth = this.container.width;
39735
39902
  resizeEventInfo.settings = this.settings;
39736
39903
  this.onResize(resizeEventInfo);
39737
- this.renderer.updateSettings(this.settings);
39738
- this.renderer.width = this.container.width;
39739
- this.renderer.resizeRender();
39904
+ this._renderer.updateSettings(this.settings);
39905
+ this._renderer.width = this.container.width;
39906
+ this._renderer.resizeRender();
39740
39907
  }
39741
39908
  }
39742
- appendRenderResult(result) {
39743
- if (result) {
39909
+ appendRenderResult(result, isLast) {
39910
+ // resizing the canvas and wrapper elements at the end is enough
39911
+ // it avoids flickering on resizes and re-renders.
39912
+ // the individual partials are anyhow sized correctly
39913
+ if (isLast) {
39744
39914
  this.canvasElement.width = result.totalWidth;
39745
39915
  this.canvasElement.height = result.totalHeight;
39746
39916
  if (this._cursorWrapper) {
39747
39917
  this._cursorWrapper.width = result.totalWidth;
39748
39918
  this._cursorWrapper.height = result.totalHeight;
39749
39919
  }
39750
- if (result.width > 0 || result.height > 0) {
39751
- this.uiFacade.beginAppendRenderResults(result);
39752
- }
39753
39920
  }
39754
- else {
39921
+ if (result.width > 0 || result.height > 0) {
39755
39922
  this.uiFacade.beginAppendRenderResults(result);
39756
39923
  }
39924
+ if (isLast) {
39925
+ this.uiFacade.beginAppendRenderResults(null);
39926
+ }
39757
39927
  }
39758
39928
  updateRenderResult(result) {
39759
39929
  if (result && result.renderResult) {
@@ -39915,13 +40085,10 @@
39915
40085
  * ```
39916
40086
  */
39917
40087
  render() {
39918
- if (!this.renderer) {
39919
- return;
39920
- }
39921
40088
  if (this.uiFacade.canRender) {
39922
40089
  // when font is finally loaded, start rendering
39923
- this.renderer.width = this.container.width;
39924
- this.renderer.renderScore(this.score, this._trackIndexes);
40090
+ this._renderer.width = this.container.width;
40091
+ this._renderer.renderScore(this.score, this._trackIndexes);
39925
40092
  }
39926
40093
  else {
39927
40094
  this.uiFacade.canRenderChanged.on(() => this.render());
@@ -39996,7 +40163,7 @@
39996
40163
  * @since 1.5.0
39997
40164
  */
39998
40165
  get boundsLookup() {
39999
- return this.renderer.boundsLookup;
40166
+ return this._renderer.boundsLookup;
40000
40167
  }
40001
40168
  /**
40002
40169
  * The alphaSynth player used for playback.
@@ -40428,6 +40595,10 @@
40428
40595
  this._previousTick = 0;
40429
40596
  this.destroyCursors();
40430
40597
  }
40598
+ /**
40599
+ *
40600
+ * @returns true if a new player was created, false if no player was created (includes destroy & reuse of the current one)
40601
+ */
40431
40602
  setupOrDestroyPlayer() {
40432
40603
  let mode = this.settings.player.playerMode;
40433
40604
  if (mode === exports.PlayerMode.EnabledAutomatic) {
@@ -40445,6 +40616,7 @@
40445
40616
  let newPlayer = null;
40446
40617
  if (mode !== this._actualPlayerMode) {
40447
40618
  this.destroyPlayer();
40619
+ this.updateCursors();
40448
40620
  switch (mode) {
40449
40621
  case exports.PlayerMode.Disabled:
40450
40622
  newPlayer = null;
@@ -40462,9 +40634,9 @@
40462
40634
  }
40463
40635
  else {
40464
40636
  // no change in player mode, just update song info if needed
40465
- return true;
40637
+ this.updateCursors();
40638
+ return false;
40466
40639
  }
40467
- this.updateCursors();
40468
40640
  this._actualPlayerMode = mode;
40469
40641
  if (!newPlayer) {
40470
40642
  return false;
@@ -40472,6 +40644,13 @@
40472
40644
  this._player.instance = newPlayer;
40473
40645
  return false;
40474
40646
  }
40647
+ /**
40648
+ * Re-creates the midi for the current score and loads it.
40649
+ * @remarks
40650
+ * This will result in the player to stop playback. Some setting changes require re-genration of the midi song.
40651
+ * @category Methods - Player
40652
+ * @since 1.6.0
40653
+ */
40475
40654
  loadMidiForScore() {
40476
40655
  if (!this.score) {
40477
40656
  return;
@@ -40875,6 +41054,7 @@
40875
41054
  this._barCursor = cursors.barCursor;
40876
41055
  this._beatCursor = cursors.beatCursor;
40877
41056
  this._selectionWrapper = cursors.selectionWrapper;
41057
+ this._isInitialBeatCursorUpdate = true;
40878
41058
  }
40879
41059
  if (this._currentBeat !== null) {
40880
41060
  this.cursorUpdateBeat(this._currentBeat, false, this._previousTick > 10, 1, true);
@@ -40914,7 +41094,7 @@
40914
41094
  if (!beat) {
40915
41095
  return;
40916
41096
  }
40917
- const cache = this.renderer.boundsLookup;
41097
+ const cache = this._renderer.boundsLookup;
40918
41098
  if (!cache) {
40919
41099
  return;
40920
41100
  }
@@ -41037,6 +41217,7 @@
41037
41217
  if (isPlayingUpdate) {
41038
41218
  // we do not "reset" the cursor if we are smoothly moving from left to right.
41039
41219
  const jumpCursor = !previousBeatBounds ||
41220
+ this._isInitialBeatCursorUpdate ||
41040
41221
  barBounds.y !== previousBeatBounds.barBounds.masterBarBounds.visualBounds.y ||
41041
41222
  startBeatX < previousBeatBounds.onNotesX ||
41042
41223
  barBoundings.index > previousBeatBounds.barBounds.masterBarBounds.index + 1;
@@ -41061,13 +41242,16 @@
41061
41242
  }
41062
41243
  else {
41063
41244
  // ticking cursor
41245
+ beatCursor.transitionToX(0, startBeatX);
41064
41246
  beatCursor.setBounds(startBeatX, barBounds.y, 1, barBounds.h);
41065
41247
  }
41248
+ this._isInitialBeatCursorUpdate = false;
41066
41249
  }
41067
- // if playing, animate the cursor to the next beat
41068
- if (this.settings.player.enableElementHighlighting) {
41069
- this.uiFacade.removeHighlights();
41250
+ else {
41251
+ this._isInitialBeatCursorUpdate = true;
41070
41252
  }
41253
+ // if playing, animate the cursor to the next beat
41254
+ this.uiFacade.removeHighlights();
41071
41255
  // actively playing? -> animate cursor and highlight items
41072
41256
  let shouldNotifyBeatChange = false;
41073
41257
  if (isPlayingUpdate) {
@@ -41231,11 +41415,11 @@
41231
41415
  }
41232
41416
  const relX = e.getX(this.canvasElement);
41233
41417
  const relY = e.getY(this.canvasElement);
41234
- const beat = this.renderer.boundsLookup?.getBeatAtPos(relX, relY) ?? null;
41418
+ const beat = this._renderer.boundsLookup?.getBeatAtPos(relX, relY) ?? null;
41235
41419
  if (beat) {
41236
41420
  this.onBeatMouseDown(e, beat);
41237
41421
  if (this.settings.core.includeNoteBounds) {
41238
- const note = this.renderer.boundsLookup?.getNoteAtPos(beat, relX, relY);
41422
+ const note = this._renderer.boundsLookup?.getNoteAtPos(beat, relX, relY);
41239
41423
  if (note) {
41240
41424
  this.onNoteMouseDown(e, note);
41241
41425
  }
@@ -41248,11 +41432,11 @@
41248
41432
  }
41249
41433
  const relX = e.getX(this.canvasElement);
41250
41434
  const relY = e.getY(this.canvasElement);
41251
- const beat = this.renderer.boundsLookup?.getBeatAtPos(relX, relY) ?? null;
41435
+ const beat = this._renderer.boundsLookup?.getBeatAtPos(relX, relY) ?? null;
41252
41436
  if (beat) {
41253
41437
  this.onBeatMouseMove(e, beat);
41254
41438
  if (this._noteMouseDown) {
41255
- const note = this.renderer.boundsLookup?.getNoteAtPos(beat, relX, relY);
41439
+ const note = this._renderer.boundsLookup?.getNoteAtPos(beat, relX, relY);
41256
41440
  if (note) {
41257
41441
  this.onNoteMouseMove(e, note);
41258
41442
  }
@@ -41268,11 +41452,11 @@
41268
41452
  }
41269
41453
  const relX = e.getX(this.canvasElement);
41270
41454
  const relY = e.getY(this.canvasElement);
41271
- const beat = this.renderer.boundsLookup?.getBeatAtPos(relX, relY) ?? null;
41455
+ const beat = this._renderer.boundsLookup?.getBeatAtPos(relX, relY) ?? null;
41272
41456
  this.onBeatMouseUp(e, beat);
41273
41457
  if (this._noteMouseDown) {
41274
41458
  if (beat) {
41275
- const note = this.renderer.boundsLookup?.getNoteAtPos(beat, relX, relY) ?? null;
41459
+ const note = this._renderer.boundsLookup?.getNoteAtPos(beat, relX, relY) ?? null;
41276
41460
  this.onNoteMouseUp(e, note);
41277
41461
  }
41278
41462
  else {
@@ -41280,7 +41464,7 @@
41280
41464
  }
41281
41465
  }
41282
41466
  });
41283
- this.renderer.postRenderFinished.on(() => {
41467
+ this._renderer.postRenderFinished.on(() => {
41284
41468
  if (!this._selectionStart ||
41285
41469
  this.settings.player.playerMode === exports.PlayerMode.Disabled ||
41286
41470
  !this.settings.player.enableCursor ||
@@ -41291,7 +41475,7 @@
41291
41475
  });
41292
41476
  }
41293
41477
  cursorSelectRange(startBeat, endBeat) {
41294
- const cache = this.renderer.boundsLookup;
41478
+ const cache = this._renderer.boundsLookup;
41295
41479
  if (!cache) {
41296
41480
  return;
41297
41481
  }
@@ -41360,7 +41544,8 @@
41360
41544
  }
41361
41545
  this.scoreLoaded.trigger(score);
41362
41546
  this.uiFacade.triggerEvent(this.container, 'scoreLoaded', score);
41363
- if (this.setupOrDestroyPlayer()) {
41547
+ if (!this.setupOrDestroyPlayer()) {
41548
+ // feed midi into current player (a new player will trigger a midi generation once the player is ready)
41364
41549
  this.loadMidiForScore();
41365
41550
  }
41366
41551
  }
@@ -41390,7 +41575,7 @@
41390
41575
  return;
41391
41576
  }
41392
41577
  this._currentBeat = null;
41393
- this.cursorUpdateTick(this._previousTick, false, 1, this._previousTick > 10);
41578
+ this.cursorUpdateTick(this._previousTick, false, 1, true, true);
41394
41579
  this.postRenderFinished.trigger();
41395
41580
  this.uiFacade.triggerEvent(this.container, 'postRenderFinished', null);
41396
41581
  }
@@ -46946,7 +47131,7 @@
46946
47131
  return this.masterBarsRenderers[0].masterBar.index;
46947
47132
  }
46948
47133
  get lastBarIndex() {
46949
- return this.masterBarsRenderers[this.masterBarsRenderers.length - 1].masterBar.index;
47134
+ return this.masterBarsRenderers[this.masterBarsRenderers.length - 1].lastMasterBarIndex;
46950
47135
  }
46951
47136
  addMasterBarRenderers(tracks, renderers) {
46952
47137
  if (tracks.length === 0) {
@@ -47760,6 +47945,9 @@
47760
47945
  }
47761
47946
  }
47762
47947
  }
47948
+ else {
47949
+ this.tuningGlyph = null;
47950
+ }
47763
47951
  }
47764
47952
  // chord diagram glyphs
47765
47953
  if (notation.isNotationElementVisible(exports.NotationElement.ChordDiagrams)) {
@@ -47788,6 +47976,12 @@
47788
47976
  }
47789
47977
  }
47790
47978
  }
47979
+ if (this.chordDiagrams.isEmpty) {
47980
+ this.chordDiagrams = null;
47981
+ }
47982
+ }
47983
+ else {
47984
+ this.chordDiagrams = null;
47791
47985
  }
47792
47986
  }
47793
47987
  createEmptyStaffSystem() {
@@ -60531,9 +60725,9 @@
60531
60725
  print(`build date: ${VersionInfo.date}`);
60532
60726
  }
60533
60727
  }
60534
- VersionInfo.version = '1.6.0-alpha.1409';
60535
- VersionInfo.date = '2025-05-14T02:06:32.990Z';
60536
- VersionInfo.commit = 'f91fed13b0a0946b3fa9306b480ddf8044b948e2';
60728
+ VersionInfo.version = '1.6.0-alpha.1416';
60729
+ VersionInfo.date = '2025-05-19T16:41:23.634Z';
60730
+ VersionInfo.commit = '4aff072e1be5292482c3d77f434dd1555b6cbb8d';
60537
60731
 
60538
60732
  /**
60539
60733
  * A factory for custom layout engines.
@@ -64847,9 +65041,11 @@
64847
65041
  ActiveBeatsChangedEventArgs,
64848
65042
  AlphaSynth,
64849
65043
  AlphaSynthAudioWorkletOutput,
65044
+ AlphaSynthBase,
64850
65045
  AlphaSynthScriptProcessorOutput,
64851
65046
  AlphaSynthWebAudioOutputBase,
64852
65047
  AlphaSynthWebWorkerApi,
65048
+ BackingTrackSyncPoint,
64853
65049
  CircularSampleBuffer,
64854
65050
  MidiEventsPlayedEventArgs,
64855
65051
  PlaybackRange,