@coderline/alphatab 1.9.0-alpha.1855 → 1.9.0-alpha.1861

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.9.0-alpha.1855 (develop, build 1855)
2
+ * alphaTab v1.9.0-alpha.1861 (develop, build 1861)
3
3
  *
4
4
  * Copyright © 2026, Daniel Kuschny and Contributors, All rights reserved.
5
5
  *
@@ -190,9 +190,9 @@
190
190
  * @internal
191
191
  */
192
192
  var VersionInfo = class VersionInfo {
193
- static version = "1.9.0-alpha.1855";
194
- static date = "2026-07-06T04:23:13.862Z";
195
- static commit = "acae7e9eafc26b0209712e3c3d0c2f8564e25148";
193
+ static version = "1.9.0-alpha.1861";
194
+ static date = "2026-07-11T03:34:14.452Z";
195
+ static commit = "18845390986e826fff8ae285ee3630080dbd6653";
196
196
  static print(print) {
197
197
  print(`alphaTab ${VersionInfo.version}`);
198
198
  print(`commit: ${VersionInfo.commit}`);
@@ -18191,18 +18191,24 @@
18191
18191
  _lyrics = [];
18192
18192
  _barCount = 0;
18193
18193
  _trackCount = 0;
18194
- _playbackInfos = [];
18194
+ /**
18195
+ * For 4 ports, 16 channels of information
18196
+ */
18197
+ _midiChannelInfo = [];
18195
18198
  _doubleBars = /* @__PURE__ */ new Set();
18196
18199
  _clefsPerTrack = /* @__PURE__ */ new Map();
18197
18200
  _keySignatures = /* @__PURE__ */ new Map();
18198
18201
  _beatTextChunksByTrack = /* @__PURE__ */ new Map();
18199
18202
  _directionLookup = /* @__PURE__ */ new Map();
18200
18203
  _initialTempo;
18204
+ _stringEncoding = "";
18201
18205
  get name() {
18202
18206
  return "Guitar Pro 3-5";
18203
18207
  }
18204
18208
  readScore() {
18205
18209
  this._directionLookup.clear();
18210
+ if (this.settings.importer.encoding !== "utf-8") this._stringEncoding = this.settings.importer.encoding;
18211
+ else this._stringEncoding = this.settings.importer.gp3To5encoding;
18206
18212
  this.readVersion();
18207
18213
  this._score = new Score();
18208
18214
  this.readScoreInformation();
@@ -18212,7 +18218,7 @@
18212
18218
  this._initialTempo = Automation.buildTempoAutomation(false, 0, 0, 0);
18213
18219
  if (this._versionNumber >= 500) {
18214
18220
  this.readPageSetup();
18215
- this._initialTempo.text = GpBinaryHelpers.gpReadStringIntByte(this.data, this.settings.importer.encoding, this.settings.importer.maxDecodingBufferSize);
18221
+ this._initialTempo.text = GpBinaryHelpers.gpReadStringIntByte(this.data, this._stringEncoding, this.settings.importer.maxDecodingBufferSize);
18216
18222
  }
18217
18223
  this._initialTempo.value = IOHelper.readInt32LE(this.data);
18218
18224
  if (this._versionNumber >= 510) GpBinaryHelpers.gpReadBool(this.data);
@@ -18271,7 +18277,7 @@
18271
18277
  directionsList.push(direction);
18272
18278
  }
18273
18279
  readVersion() {
18274
- let version = GpBinaryHelpers.gpReadStringByteLength(this.data, 30, this.settings.importer.encoding);
18280
+ let version = GpBinaryHelpers.gpReadStringByteLength(this.data, 30, this._stringEncoding);
18275
18281
  if (!version.startsWith(Gp3To5Importer._versionString)) throw new UnsupportedFormatError("Unsupported format");
18276
18282
  version = version.substr(Gp3To5Importer._versionString.length + 1);
18277
18283
  const dot = version.indexOf(String.fromCharCode(46));
@@ -18279,21 +18285,21 @@
18279
18285
  Logger.debug(this.name, `Guitar Pro version ${version} detected`);
18280
18286
  }
18281
18287
  readScoreInformation() {
18282
- this._score.title = GpBinaryHelpers.gpReadStringIntUnused(this.data, this.settings.importer.encoding, this.settings.importer.maxDecodingBufferSize);
18283
- this._score.subTitle = GpBinaryHelpers.gpReadStringIntUnused(this.data, this.settings.importer.encoding, this.settings.importer.maxDecodingBufferSize);
18284
- this._score.artist = GpBinaryHelpers.gpReadStringIntUnused(this.data, this.settings.importer.encoding, this.settings.importer.maxDecodingBufferSize);
18285
- this._score.album = GpBinaryHelpers.gpReadStringIntUnused(this.data, this.settings.importer.encoding, this.settings.importer.maxDecodingBufferSize);
18286
- this._score.words = GpBinaryHelpers.gpReadStringIntUnused(this.data, this.settings.importer.encoding, this.settings.importer.maxDecodingBufferSize);
18287
- this._score.music = this._versionNumber >= 500 ? GpBinaryHelpers.gpReadStringIntUnused(this.data, this.settings.importer.encoding, this.settings.importer.maxDecodingBufferSize) : this._score.words;
18288
- this._score.copyright = GpBinaryHelpers.gpReadStringIntUnused(this.data, this.settings.importer.encoding, this.settings.importer.maxDecodingBufferSize);
18289
- this._score.tab = GpBinaryHelpers.gpReadStringIntUnused(this.data, this.settings.importer.encoding, this.settings.importer.maxDecodingBufferSize);
18290
- this._score.instructions = GpBinaryHelpers.gpReadStringIntUnused(this.data, this.settings.importer.encoding, this.settings.importer.maxDecodingBufferSize);
18288
+ this._score.title = GpBinaryHelpers.gpReadStringIntUnused(this.data, this._stringEncoding, this.settings.importer.maxDecodingBufferSize);
18289
+ this._score.subTitle = GpBinaryHelpers.gpReadStringIntUnused(this.data, this._stringEncoding, this.settings.importer.maxDecodingBufferSize);
18290
+ this._score.artist = GpBinaryHelpers.gpReadStringIntUnused(this.data, this._stringEncoding, this.settings.importer.maxDecodingBufferSize);
18291
+ this._score.album = GpBinaryHelpers.gpReadStringIntUnused(this.data, this._stringEncoding, this.settings.importer.maxDecodingBufferSize);
18292
+ this._score.words = GpBinaryHelpers.gpReadStringIntUnused(this.data, this._stringEncoding, this.settings.importer.maxDecodingBufferSize);
18293
+ this._score.music = this._versionNumber >= 500 ? GpBinaryHelpers.gpReadStringIntUnused(this.data, this._stringEncoding, this.settings.importer.maxDecodingBufferSize) : this._score.words;
18294
+ this._score.copyright = GpBinaryHelpers.gpReadStringIntUnused(this.data, this._stringEncoding, this.settings.importer.maxDecodingBufferSize);
18295
+ this._score.tab = GpBinaryHelpers.gpReadStringIntUnused(this.data, this._stringEncoding, this.settings.importer.maxDecodingBufferSize);
18296
+ this._score.instructions = GpBinaryHelpers.gpReadStringIntUnused(this.data, this._stringEncoding, this.settings.importer.maxDecodingBufferSize);
18291
18297
  const noticeLines = IOHelper.readInt32LE(this.data);
18292
18298
  this._ensureLoopBoundary(noticeLines, Gp3To5Importer._maxNoticeLines, "notice line count");
18293
18299
  let notice = "";
18294
18300
  for (let i = 0; i < noticeLines; i++) {
18295
18301
  if (i > 0) notice += "\r\n";
18296
- notice += GpBinaryHelpers.gpReadStringIntUnused(this.data, this.settings.importer.encoding, this.settings.importer.maxDecodingBufferSize)?.toString();
18302
+ notice += GpBinaryHelpers.gpReadStringIntUnused(this.data, this._stringEncoding, this.settings.importer.maxDecodingBufferSize)?.toString();
18297
18303
  }
18298
18304
  this._score.notices = notice;
18299
18305
  }
@@ -18311,7 +18317,7 @@
18311
18317
  for (let i = 0; i < 5; i++) {
18312
18318
  const lyrics = new Lyrics();
18313
18319
  lyrics.startBar = IOHelper.readInt32LE(this.data) - 1;
18314
- lyrics.text = GpBinaryHelpers.gpReadStringInt(this.data, this.settings.importer.encoding, this.settings.importer.maxDecodingBufferSize);
18320
+ lyrics.text = GpBinaryHelpers.gpReadStringInt(this.data, this._stringEncoding, this.settings.importer.maxDecodingBufferSize);
18315
18321
  this._lyrics.push(lyrics);
18316
18322
  }
18317
18323
  }
@@ -18319,37 +18325,43 @@
18319
18325
  this.data.skip(28);
18320
18326
  const flags = IOHelper.readInt16LE(this.data);
18321
18327
  ModelUtils.getOrCreateHeaderFooterStyle(this._score, ScoreSubElement.Title).isVisible = (flags & 1) !== 0;
18322
- ModelUtils.getOrCreateHeaderFooterStyle(this._score, ScoreSubElement.Title).template = GpBinaryHelpers.gpReadStringIntByte(this.data, this.settings.importer.encoding, this.settings.importer.maxDecodingBufferSize);
18328
+ ModelUtils.getOrCreateHeaderFooterStyle(this._score, ScoreSubElement.Title).template = GpBinaryHelpers.gpReadStringIntByte(this.data, this._stringEncoding, this.settings.importer.maxDecodingBufferSize);
18323
18329
  ModelUtils.getOrCreateHeaderFooterStyle(this._score, ScoreSubElement.SubTitle).isVisible = (flags & 2) !== 0;
18324
- ModelUtils.getOrCreateHeaderFooterStyle(this._score, ScoreSubElement.SubTitle).template = GpBinaryHelpers.gpReadStringIntByte(this.data, this.settings.importer.encoding, this.settings.importer.maxDecodingBufferSize);
18330
+ ModelUtils.getOrCreateHeaderFooterStyle(this._score, ScoreSubElement.SubTitle).template = GpBinaryHelpers.gpReadStringIntByte(this.data, this._stringEncoding, this.settings.importer.maxDecodingBufferSize);
18325
18331
  ModelUtils.getOrCreateHeaderFooterStyle(this._score, ScoreSubElement.Artist).isVisible = (flags & 4) !== 0;
18326
- ModelUtils.getOrCreateHeaderFooterStyle(this._score, ScoreSubElement.Artist).template = GpBinaryHelpers.gpReadStringIntByte(this.data, this.settings.importer.encoding, this.settings.importer.maxDecodingBufferSize);
18332
+ ModelUtils.getOrCreateHeaderFooterStyle(this._score, ScoreSubElement.Artist).template = GpBinaryHelpers.gpReadStringIntByte(this.data, this._stringEncoding, this.settings.importer.maxDecodingBufferSize);
18327
18333
  ModelUtils.getOrCreateHeaderFooterStyle(this._score, ScoreSubElement.Album).isVisible = (flags & 8) !== 0;
18328
- ModelUtils.getOrCreateHeaderFooterStyle(this._score, ScoreSubElement.Album).template = GpBinaryHelpers.gpReadStringIntByte(this.data, this.settings.importer.encoding, this.settings.importer.maxDecodingBufferSize);
18334
+ ModelUtils.getOrCreateHeaderFooterStyle(this._score, ScoreSubElement.Album).template = GpBinaryHelpers.gpReadStringIntByte(this.data, this._stringEncoding, this.settings.importer.maxDecodingBufferSize);
18329
18335
  ModelUtils.getOrCreateHeaderFooterStyle(this._score, ScoreSubElement.Words).isVisible = (flags & 16) !== 0;
18330
- ModelUtils.getOrCreateHeaderFooterStyle(this._score, ScoreSubElement.Words).template = GpBinaryHelpers.gpReadStringIntByte(this.data, this.settings.importer.encoding, this.settings.importer.maxDecodingBufferSize);
18336
+ ModelUtils.getOrCreateHeaderFooterStyle(this._score, ScoreSubElement.Words).template = GpBinaryHelpers.gpReadStringIntByte(this.data, this._stringEncoding, this.settings.importer.maxDecodingBufferSize);
18331
18337
  ModelUtils.getOrCreateHeaderFooterStyle(this._score, ScoreSubElement.Music).isVisible = (flags & 32) !== 0;
18332
- ModelUtils.getOrCreateHeaderFooterStyle(this._score, ScoreSubElement.Music).template = GpBinaryHelpers.gpReadStringIntByte(this.data, this.settings.importer.encoding, this.settings.importer.maxDecodingBufferSize);
18338
+ ModelUtils.getOrCreateHeaderFooterStyle(this._score, ScoreSubElement.Music).template = GpBinaryHelpers.gpReadStringIntByte(this.data, this._stringEncoding, this.settings.importer.maxDecodingBufferSize);
18333
18339
  ModelUtils.getOrCreateHeaderFooterStyle(this._score, ScoreSubElement.WordsAndMusic).isVisible = (flags & 64) !== 0;
18334
- ModelUtils.getOrCreateHeaderFooterStyle(this._score, ScoreSubElement.WordsAndMusic).template = GpBinaryHelpers.gpReadStringIntByte(this.data, this.settings.importer.encoding, this.settings.importer.maxDecodingBufferSize);
18340
+ ModelUtils.getOrCreateHeaderFooterStyle(this._score, ScoreSubElement.WordsAndMusic).template = GpBinaryHelpers.gpReadStringIntByte(this.data, this._stringEncoding, this.settings.importer.maxDecodingBufferSize);
18335
18341
  ModelUtils.getOrCreateHeaderFooterStyle(this._score, ScoreSubElement.Copyright).isVisible = (flags & 128) !== 0;
18336
- ModelUtils.getOrCreateHeaderFooterStyle(this._score, ScoreSubElement.Copyright).template = GpBinaryHelpers.gpReadStringIntByte(this.data, this.settings.importer.encoding, this.settings.importer.maxDecodingBufferSize);
18342
+ ModelUtils.getOrCreateHeaderFooterStyle(this._score, ScoreSubElement.Copyright).template = GpBinaryHelpers.gpReadStringIntByte(this.data, this._stringEncoding, this.settings.importer.maxDecodingBufferSize);
18337
18343
  ModelUtils.getOrCreateHeaderFooterStyle(this._score, ScoreSubElement.CopyrightSecondLine).isVisible = (flags & 128) !== 0;
18338
- ModelUtils.getOrCreateHeaderFooterStyle(this._score, ScoreSubElement.CopyrightSecondLine).template = GpBinaryHelpers.gpReadStringIntByte(this.data, this.settings.importer.encoding, this.settings.importer.maxDecodingBufferSize);
18339
- GpBinaryHelpers.gpReadStringIntByte(this.data, this.settings.importer.encoding, this.settings.importer.maxDecodingBufferSize);
18344
+ ModelUtils.getOrCreateHeaderFooterStyle(this._score, ScoreSubElement.CopyrightSecondLine).template = GpBinaryHelpers.gpReadStringIntByte(this.data, this._stringEncoding, this.settings.importer.maxDecodingBufferSize);
18345
+ GpBinaryHelpers.gpReadStringIntByte(this.data, this._stringEncoding, this.settings.importer.maxDecodingBufferSize);
18340
18346
  }
18341
18347
  readPlaybackInfos() {
18342
- this._playbackInfos = [];
18343
- let channel = 0;
18344
- for (let i = 0; i < 64; i++) {
18345
- const info = new PlaybackInformation();
18346
- info.primaryChannel = channel++;
18347
- info.secondaryChannel = channel++;
18348
- info.program = IOHelper.readInt32LE(this.data);
18349
- info.volume = this.data.readByte();
18350
- info.balance = this.data.readByte();
18351
- this.data.skip(6);
18352
- this._playbackInfos.push(info);
18348
+ this._midiChannelInfo = [];
18349
+ for (let port = 0; port < 4; port++) {
18350
+ const portInfo = [];
18351
+ this._midiChannelInfo.push(portInfo);
18352
+ for (let channel = 0; channel < 16; channel++) {
18353
+ const info = {
18354
+ program: IOHelper.readInt32LE(this.data),
18355
+ volume: this.data.readByte(),
18356
+ balance: this.data.readByte(),
18357
+ chorus: this.data.readByte(),
18358
+ reverb: this.data.readByte(),
18359
+ phase: this.data.readByte(),
18360
+ tremolo: this.data.readByte()
18361
+ };
18362
+ this.data.skip(2);
18363
+ portInfo.push(info);
18364
+ }
18353
18365
  }
18354
18366
  }
18355
18367
  readMasterBars() {
@@ -18386,7 +18398,7 @@
18386
18398
  }
18387
18399
  if ((flags & 32) !== 0) {
18388
18400
  const section = new Section();
18389
- section.text = GpBinaryHelpers.gpReadStringIntByte(this.data, this.settings.importer.encoding, this.settings.importer.maxDecodingBufferSize);
18401
+ section.text = GpBinaryHelpers.gpReadStringIntByte(this.data, this._stringEncoding, this.settings.importer.maxDecodingBufferSize);
18390
18402
  section.marker = "";
18391
18403
  GpBinaryHelpers.gpReadColor(this.data, false);
18392
18404
  newMasterBar.section = section;
@@ -18425,7 +18437,7 @@
18425
18437
  this._score.addTrack(newTrack);
18426
18438
  const mainStaff = newTrack.staves[0];
18427
18439
  const flags = this.data.readByte();
18428
- newTrack.name = GpBinaryHelpers.gpReadStringByteLength(this.data, 40, this.settings.importer.encoding);
18440
+ newTrack.name = GpBinaryHelpers.gpReadStringByteLength(this.data, 40, this._stringEncoding);
18429
18441
  if ((flags & 1) !== 0) mainStaff.isPercussion = true;
18430
18442
  if (this._versionNumber >= 500) newTrack.isVisibleOnMultiTrack = (flags & 8) !== 0;
18431
18443
  if (this._score.stylesheet.perTrackDisplayTuning === null) this._score.stylesheet.perTrackDisplayTuning = /* @__PURE__ */ new Map();
@@ -18437,19 +18449,22 @@
18437
18449
  if (stringCount > i) tuning.push(stringTuning);
18438
18450
  }
18439
18451
  mainStaff.stringTuning.tunings = tuning;
18440
- const port = IOHelper.readInt32LE(this.data);
18441
- const index = IOHelper.readInt32LE(this.data) - 1;
18452
+ const port = IOHelper.readInt32LE(this.data) - 1;
18453
+ const channel = IOHelper.readInt32LE(this.data) - 1;
18442
18454
  const effectChannel = IOHelper.readInt32LE(this.data) - 1;
18443
18455
  this.data.skip(4);
18444
- if (index >= 0 && index < this._playbackInfos.length) {
18445
- const info = this._playbackInfos[index];
18446
- info.port = port;
18447
- info.isSolo = (flags & 16) !== 0;
18448
- info.isMute = (flags & 32) !== 0;
18449
- info.secondaryChannel = effectChannel;
18450
- if (GeneralMidi.isGuitar(info.program)) mainStaff.displayTranspositionPitch = -12;
18451
- newTrack.playbackInfo = info;
18452
- }
18456
+ const mainMidiChannelInfo = this._midiChannelInfo[port][channel];
18457
+ const trackPlaybackInfo = new PlaybackInformation();
18458
+ trackPlaybackInfo.volume = mainMidiChannelInfo.volume;
18459
+ trackPlaybackInfo.balance = mainMidiChannelInfo.balance;
18460
+ trackPlaybackInfo.port = port;
18461
+ trackPlaybackInfo.program = mainMidiChannelInfo.program;
18462
+ trackPlaybackInfo.primaryChannel = channel;
18463
+ trackPlaybackInfo.secondaryChannel = effectChannel;
18464
+ trackPlaybackInfo.isSolo = (flags & 16) !== 0;
18465
+ trackPlaybackInfo.isMute = (flags & 32) !== 0;
18466
+ if (GeneralMidi.isGuitar(trackPlaybackInfo.program)) mainStaff.displayTranspositionPitch = -12;
18467
+ newTrack.playbackInfo = trackPlaybackInfo;
18453
18468
  mainStaff.capo = IOHelper.readInt32LE(this.data);
18454
18469
  newTrack.color = GpBinaryHelpers.gpReadColor(this.data, false);
18455
18470
  if (this._versionNumber >= 500) {
@@ -18473,8 +18488,8 @@
18473
18488
  this._readRseBank();
18474
18489
  if (this._versionNumber >= 510) {
18475
18490
  this.data.skip(4);
18476
- GpBinaryHelpers.gpReadStringIntByte(this.data, this.settings.importer.encoding, this.settings.importer.maxDecodingBufferSize);
18477
- GpBinaryHelpers.gpReadStringIntByte(this.data, this.settings.importer.encoding, this.settings.importer.maxDecodingBufferSize);
18491
+ GpBinaryHelpers.gpReadStringIntByte(this.data, this._stringEncoding, this.settings.importer.maxDecodingBufferSize);
18492
+ GpBinaryHelpers.gpReadStringIntByte(this.data, this._stringEncoding, this.settings.importer.maxDecodingBufferSize);
18478
18493
  }
18479
18494
  } else if (tuning[tuning.length - 1] < Gp3To5Importer._bassClefTuningThreshold) this._clefsPerTrack.set(newTrack.index, Clef.F4);
18480
18495
  else this._clefsPerTrack.set(newTrack.index, Clef.G2);
@@ -18577,7 +18592,7 @@
18577
18592
  if ((flags & 2) !== 0) this.readChord(newBeat);
18578
18593
  const beatTextAsLyrics = this.settings.importer.beatTextAsLyrics && track.index !== this._lyricsTrack;
18579
18594
  if ((flags & 4) !== 0) {
18580
- const text = GpBinaryHelpers.gpReadStringIntUnused(this.data, this.settings.importer.encoding, this.settings.importer.maxDecodingBufferSize);
18595
+ const text = GpBinaryHelpers.gpReadStringIntUnused(this.data, this._stringEncoding, this.settings.importer.maxDecodingBufferSize);
18581
18596
  if (beatTextAsLyrics) {
18582
18597
  const lyrics = new Lyrics();
18583
18598
  lyrics.text = text.trim();
@@ -18624,7 +18639,7 @@
18624
18639
  const chordId = ModelUtils.newGuid();
18625
18640
  if (this._versionNumber >= 500) {
18626
18641
  this.data.skip(17);
18627
- chord.name = GpBinaryHelpers.gpReadStringByteLength(this.data, 21, this.settings.importer.encoding);
18642
+ chord.name = GpBinaryHelpers.gpReadStringByteLength(this.data, 21, this._stringEncoding);
18628
18643
  this.data.skip(4);
18629
18644
  chord.firstFret = IOHelper.readInt32LE(this.data);
18630
18645
  for (let i = 0; i < 7; i++) {
@@ -18638,7 +18653,7 @@
18638
18653
  this.data.skip(26);
18639
18654
  } else if (this.data.readByte() !== 0) if (this._versionNumber >= 400) {
18640
18655
  this.data.skip(16);
18641
- chord.name = GpBinaryHelpers.gpReadStringByteLength(this.data, 21, this.settings.importer.encoding);
18656
+ chord.name = GpBinaryHelpers.gpReadStringByteLength(this.data, 21, this._stringEncoding);
18642
18657
  this.data.skip(4);
18643
18658
  chord.firstFret = IOHelper.readInt32LE(this.data);
18644
18659
  for (let i = 0; i < 7; i++) {
@@ -18652,7 +18667,7 @@
18652
18667
  this.data.skip(26);
18653
18668
  } else {
18654
18669
  this.data.skip(25);
18655
- chord.name = GpBinaryHelpers.gpReadStringByteLength(this.data, 34, this.settings.importer.encoding);
18670
+ chord.name = GpBinaryHelpers.gpReadStringByteLength(this.data, 34, this._stringEncoding);
18656
18671
  chord.firstFret = IOHelper.readInt32LE(this.data);
18657
18672
  for (let i = 0; i < 6; i++) {
18658
18673
  const fret = IOHelper.readInt32LE(this.data);
@@ -18662,7 +18677,7 @@
18662
18677
  }
18663
18678
  else {
18664
18679
  const strings = this._versionNumber >= 406 ? 7 : 6;
18665
- chord.name = GpBinaryHelpers.gpReadStringIntByte(this.data, this.settings.importer.encoding, this.settings.importer.maxDecodingBufferSize);
18680
+ chord.name = GpBinaryHelpers.gpReadStringIntByte(this.data, this._stringEncoding, this.settings.importer.maxDecodingBufferSize);
18666
18681
  chord.firstFret = IOHelper.readInt32LE(this.data);
18667
18682
  if (chord.firstFret > 0) for (let i = 0; i < strings; i++) {
18668
18683
  const fret = IOHelper.readInt32LE(this.data);
@@ -18782,7 +18797,7 @@
18782
18797
  const reverb = IOHelper.readSInt8(this.data);
18783
18798
  const phaser = IOHelper.readSInt8(this.data);
18784
18799
  const tremolo = IOHelper.readSInt8(this.data);
18785
- if (this._versionNumber >= 500) tableChange.tempoName = GpBinaryHelpers.gpReadStringIntByte(this.data, this.settings.importer.encoding, this.settings.importer.maxDecodingBufferSize);
18800
+ if (this._versionNumber >= 500) tableChange.tempoName = GpBinaryHelpers.gpReadStringIntByte(this.data, this._stringEncoding, this.settings.importer.maxDecodingBufferSize);
18786
18801
  tableChange.tempo = IOHelper.readInt32LE(this.data);
18787
18802
  if (tableChange.volume >= 0) this.data.readByte();
18788
18803
  if (tableChange.balance >= 0) this.data.readByte();
@@ -18801,8 +18816,8 @@
18801
18816
  else if (wahType >= 0) beat.wahPedal = WahPedal.Open;
18802
18817
  }
18803
18818
  if (this._versionNumber >= 510) {
18804
- GpBinaryHelpers.gpReadStringIntByte(this.data, this.settings.importer.encoding, this.settings.importer.maxDecodingBufferSize);
18805
- GpBinaryHelpers.gpReadStringIntByte(this.data, this.settings.importer.encoding, this.settings.importer.maxDecodingBufferSize);
18819
+ GpBinaryHelpers.gpReadStringIntByte(this.data, this._stringEncoding, this.settings.importer.maxDecodingBufferSize);
18820
+ GpBinaryHelpers.gpReadStringIntByte(this.data, this._stringEncoding, this.settings.importer.maxDecodingBufferSize);
18806
18821
  }
18807
18822
  if (tableChange.volume >= 0) {
18808
18823
  const volumeAutomation = new Automation();
@@ -22552,6 +22567,10 @@
22552
22567
  * The balance to use when playing the note (-1 if using the default track balance).
22553
22568
  */
22554
22569
  outputBalance = -1;
22570
+ /**
22571
+ * Whether this instrument was declared as an unpitched/percussion sound via `<midi-unpitched>`.
22572
+ */
22573
+ isUnpitched = false;
22555
22574
  };
22556
22575
  /**
22557
22576
  * @internal
@@ -22596,6 +22615,9 @@
22596
22615
  this.track.percussionArticulations.push(newArticulation);
22597
22616
  return index;
22598
22617
  }
22618
+ isUnpitchedInstrument(instrumentId) {
22619
+ return this.instruments.has(instrumentId) && this.instruments.get(instrumentId).isUnpitched;
22620
+ }
22599
22621
  };
22600
22622
  /**
22601
22623
  * @internal
@@ -22910,6 +22932,7 @@
22910
22932
  break;
22911
22933
  case "midi-unpitched":
22912
22934
  articulation.outputMidiNumber = Number.parseInt(c.innerText, 10) - 1;
22935
+ articulation.isUnpitched = true;
22913
22936
  break;
22914
22937
  case "volume":
22915
22938
  articulation.outputVolume = MusicXmlImporter._interpolatePercent(Number.parseFloat(c.innerText));
@@ -24328,11 +24351,15 @@
24328
24351
  note.isVisible = noteIsVisible;
24329
24352
  if (note.percussionArticulation >= 0) return;
24330
24353
  const trackInfo = this._indexToTrackInfo.get(track.index);
24331
- if (instrumentId !== null) note.percussionArticulation = trackInfo.getOrCreateArticulation(instrumentId, note);
24332
- else if (note.beat.voice.bar.staff.isPercussion && isPitched) {
24354
+ if (!isPitched) {
24355
+ note.percussionArticulation = trackInfo.getOrCreateArticulation(instrumentId ?? "", note);
24356
+ return;
24357
+ }
24358
+ if (instrumentId !== null && trackInfo.isUnpitchedInstrument(instrumentId)) note.percussionArticulation = trackInfo.getOrCreateArticulation(instrumentId, note);
24359
+ else if (note.beat.voice.bar.staff.isPercussion) {
24333
24360
  const knownArticulation = PercussionMapper.getArticulationById(note.displayValue);
24334
24361
  if (knownArticulation) note.percussionArticulation = knownArticulation.id;
24335
- } else if (!isPitched) note.percussionArticulation = trackInfo.getOrCreateArticulation("", note);
24362
+ }
24336
24363
  }
24337
24364
  _parsePlay(element, note) {
24338
24365
  for (const c of element.childElements()) switch (c.localName) {
@@ -28836,11 +28863,21 @@
28836
28863
  *
28837
28864
  * * Guitar Pro 7
28838
28865
  * * Guitar Pro 6
28839
- * * Guitar Pro 3-5
28840
28866
  * * MusicXML
28841
28867
  */
28842
28868
  encoding = "utf-8";
28843
28869
  /**
28870
+ * The text encoding to use when decoding strings within GuitarPro3-5 files.
28871
+ * @since 1.9.0
28872
+ * @defaultValue `windows-1252`
28873
+ * @category Importer
28874
+ * @remarks
28875
+ * Guitar Pro 3-5 encode strings as system specific ANSI encoding, typically Windows-1252 in western system cultures.
28876
+ * This is different to the other typically used utf-8 encoding.
28877
+ * Via this setting the Guitar Pro 3-5 specific decoding can be used.
28878
+ */
28879
+ gp3To5encoding = "windows-1252";
28880
+ /**
28844
28881
  * If part-groups should be merged into a single track (MusicXML).
28845
28882
  * @since 0.9.6
28846
28883
  * @defaultValue `false`
@@ -29164,11 +29201,45 @@
29164
29201
  * @since 0.9.7
29165
29202
  * @defaultValue `true`
29166
29203
  * @category Player
29204
+ * @json_read_only
29167
29205
  * @remarks
29168
29206
  * This setting configures whether alphaTab provides the default user interaction features like selection of the playback range and "seek on click".
29169
29207
  * By default users can select the desired playback range with the mouse and also jump to individual beats by click. This behavior can be contolled with this setting.
29208
+ * @deprecated Use {@link enableSeekToClick} and {@link enablePlaybackRangeSelection} individually
29209
+ */
29210
+ get enableUserInteraction() {
29211
+ return this.enableSeekToClick || this.enablePlaybackRangeSelection;
29212
+ }
29213
+ /**
29214
+ * @deprecated Use {@link enableSeekToClick} and {@link enablePlaybackRangeSelection} individually
29215
+ */
29216
+ set enableUserInteraction(value) {
29217
+ this.enableSeekToClick = value;
29218
+ this.enablePlaybackRangeSelection = value;
29219
+ this.resetPlaybackRangeOnClick = value;
29220
+ }
29221
+ /**
29222
+ * Whether the a click on the music sheet triggers a player seek to the note/beat at the
29223
+ * clicked location.
29224
+ * @since 1.9.0
29225
+ * @defaultValue `true`
29226
+ * @category Player
29227
+ */
29228
+ enableSeekToClick = true;
29229
+ /**
29230
+ * Whether user click and drag results in a selection defining the playback range.
29231
+ * @since 1.9.0
29232
+ * @defaultValue `true`
29233
+ * @category Player
29234
+ */
29235
+ enablePlaybackRangeSelection = true;
29236
+ /**
29237
+ * Whether a simple click (no range drag) should reset the current playback range.
29238
+ * @since 1.9.0
29239
+ * @defaultValue `true`
29240
+ * @category Player
29170
29241
  */
29171
- enableUserInteraction = true;
29242
+ resetPlaybackRangeOnClick = true;
29172
29243
  /**
29173
29244
  * The X-offset to add when scrolling.
29174
29245
  * @since 0.9.6
@@ -30192,6 +30263,7 @@
30192
30263
  if (!obj) return null;
30193
30264
  const o = /* @__PURE__ */ new Map();
30194
30265
  o.set("encoding", obj.encoding);
30266
+ o.set("gp3to5encoding", obj.gp3To5encoding);
30195
30267
  o.set("mergepartgroupsinmusicxml", obj.mergePartGroupsInMusicXml);
30196
30268
  o.set("beattextaslyrics", obj.beatTextAsLyrics);
30197
30269
  o.set("maxdecodingbuffersize", obj.maxDecodingBufferSize);
@@ -30202,6 +30274,9 @@
30202
30274
  case "encoding":
30203
30275
  obj.encoding = v;
30204
30276
  return true;
30277
+ case "gp3to5encoding":
30278
+ obj.gp3To5encoding = v;
30279
+ return true;
30205
30280
  case "mergepartgroupsinmusicxml":
30206
30281
  obj.mergePartGroupsInMusicXml = v;
30207
30282
  return true;
@@ -30321,7 +30396,9 @@
30321
30396
  o.set("enablecursor", obj.enableCursor);
30322
30397
  o.set("enableanimatedbeatcursor", obj.enableAnimatedBeatCursor);
30323
30398
  o.set("enableelementhighlighting", obj.enableElementHighlighting);
30324
- o.set("enableuserinteraction", obj.enableUserInteraction);
30399
+ o.set("enableseektoclick", obj.enableSeekToClick);
30400
+ o.set("enableplaybackrangeselection", obj.enablePlaybackRangeSelection);
30401
+ o.set("resetplaybackrangeonclick", obj.resetPlaybackRangeOnClick);
30325
30402
  o.set("scrolloffsetx", obj.scrollOffsetX);
30326
30403
  o.set("scrolloffsety", obj.scrollOffsetY);
30327
30404
  o.set("scrollmode", obj.scrollMode);
@@ -30364,6 +30441,15 @@
30364
30441
  case "enableuserinteraction":
30365
30442
  obj.enableUserInteraction = v;
30366
30443
  return true;
30444
+ case "enableseektoclick":
30445
+ obj.enableSeekToClick = v;
30446
+ return true;
30447
+ case "enableplaybackrangeselection":
30448
+ obj.enablePlaybackRangeSelection = v;
30449
+ return true;
30450
+ case "resetplaybackrangeonclick":
30451
+ obj.resetPlaybackRangeOnClick = v;
30452
+ return true;
30367
30453
  case "scrolloffsetx":
30368
30454
  obj.scrollOffsetX = v;
30369
30455
  return true;
@@ -45362,6 +45448,16 @@
45362
45448
  scaleToWidth(beatWidth) {
45363
45449
  this.width = beatWidth;
45364
45450
  }
45451
+ /**
45452
+ * Repositions this beat so its {@link onTimeX} anchor lands at `target`, used for the
45453
+ * centered full-bar note/rest (see {@link BarLayoutingInfo.isCenteredFullBar}). The default
45454
+ * shifts the whole container, matching the regular (non-centered) positioning formula.
45455
+ * {@link BeatContainerGlyph} overrides this to shift only its ink, keeping `x`/`width`
45456
+ * spanning the full bar so bounds lookups and skyline emission stay correct.
45457
+ */
45458
+ applyCenterOffset(target) {
45459
+ this.x = target - this.onTimeX;
45460
+ }
45365
45461
  };
45366
45462
  /**
45367
45463
  * @internal
@@ -45465,13 +45561,28 @@
45465
45561
  this.preNotes.renderer = this.renderer;
45466
45562
  this.preNotes.container = this;
45467
45563
  this.preNotes.doLayout();
45468
- this.onNotes.x = this.preNotes.x + this.preNotes.width;
45564
+ this._layoutOnsetX();
45469
45565
  this.onNotes.renderer = this.renderer;
45470
45566
  this.onNotes.container = this;
45471
45567
  this.onNotes.doLayout();
45472
45568
  this.createBeatTies();
45473
45569
  this.updateWidth();
45474
45570
  }
45571
+ /**
45572
+ * Resets `preNotes.x`/`onNotes.x` to their natural (un-centered) baseline.
45573
+ * Shared by {@link doLayout} and {@link applyCenterOffset} so the latter can be called
45574
+ * repeatedly (once per `_scaleToForce` pass) without compounding a previous offset.
45575
+ */
45576
+ _layoutOnsetX() {
45577
+ this.preNotes.x = 0;
45578
+ this.onNotes.x = this.preNotes.x + this.preNotes.width;
45579
+ }
45580
+ applyCenterOffset(target) {
45581
+ this._layoutOnsetX();
45582
+ const offset = target - this.onTimeX;
45583
+ this.preNotes.x = offset;
45584
+ this.onNotes.x = this.preNotes.x + this.preNotes.width;
45585
+ }
45475
45586
  createBeatTies() {
45476
45587
  let i = this.beat.notes.length - 1;
45477
45588
  while (i >= 0) this.createTies(this.beat.notes[i--]);
@@ -48561,7 +48672,7 @@
48561
48672
  }
48562
48673
  _onBeatMouseDown(originalEvent, beat) {
48563
48674
  if (this._isDestroyed) return;
48564
- if (this._hasCursor && this.settings.player.enableUserInteraction) {
48675
+ if (this._hasCursor && this.settings.player.enablePlaybackRangeSelection) {
48565
48676
  this._selectionStart = { beat };
48566
48677
  this._selectionEnd = void 0;
48567
48678
  }
@@ -48577,10 +48688,12 @@
48577
48688
  }
48578
48689
  _onBeatMouseMove(originalEvent, beat) {
48579
48690
  if (this._isDestroyed) return;
48580
- if (this.settings.player.enableUserInteraction) {
48691
+ if (this.settings.player.enablePlaybackRangeSelection) {
48581
48692
  if (!this._selectionEnd || this._selectionEnd.beat !== beat) {
48582
- this._selectionEnd = { beat };
48583
- this._cursorSelectRange(this._selectionStart, this._selectionEnd);
48693
+ if (this._selectionStart?.beat !== beat) {
48694
+ this._selectionEnd = { beat };
48695
+ this._cursorSelectRange(this._selectionStart, this._selectionEnd);
48696
+ }
48584
48697
  }
48585
48698
  }
48586
48699
  this.beatMouseMove.trigger(beat);
@@ -48593,11 +48706,30 @@
48593
48706
  }
48594
48707
  _onBeatMouseUp(originalEvent, beat) {
48595
48708
  if (this._isDestroyed) return;
48596
- if (this._hasCursor && this.settings.player.enableUserInteraction) this.applyPlaybackRangeFromHighlight();
48709
+ if (this._hasCursor) {
48710
+ let shouldSeekToBeat = beat && this.settings.player.enableSeekToClick;
48711
+ if (this.settings.player.enablePlaybackRangeSelection) {
48712
+ if (this._internalApplyPlaybackRangeFromHighlight()) shouldSeekToBeat = false;
48713
+ }
48714
+ if (shouldSeekToBeat) this._seekToBeat(beat);
48715
+ }
48597
48716
  this.beatMouseUp.trigger(beat);
48598
48717
  this.uiFacade.triggerEvent(this.container, "beatMouseUp", beat, originalEvent);
48599
48718
  this._isBeatMouseDown = false;
48600
48719
  }
48720
+ _seekToBeat(beat) {
48721
+ const tickCache = this._tickCache;
48722
+ if (!tickCache) return;
48723
+ this._currentBeat = null;
48724
+ let beatTick = tickCache.getMasterBarStart(beat.voice.bar.masterBar) + (tickCache.getRelativeBeatPlaybackRange(beat)?.startTick ?? beat.playbackStart);
48725
+ const playbackRange = this.playbackRange;
48726
+ if (playbackRange) {
48727
+ if (beatTick < playbackRange.startTick) beatTick = playbackRange.startTick;
48728
+ else if (beatTick > playbackRange.endTick) beatTick = playbackRange.endTick;
48729
+ }
48730
+ if (this._player.state === PlayerState.Paused) this._cursorUpdateTick(beatTick, false, 1);
48731
+ this.tickPosition = beatTick;
48732
+ }
48601
48733
  _onNoteMouseUp(originalEvent, note) {
48602
48734
  if (this._isDestroyed) return;
48603
48735
  this.noteMouseUp.trigger(note);
@@ -48619,7 +48751,7 @@
48619
48751
  _setupClickHandling() {
48620
48752
  this.canvasElement.mouseDown.on((e) => {
48621
48753
  if (!e.isLeftMouseButton) return;
48622
- if (this.settings.player.enableUserInteraction) e.preventDefault();
48754
+ if (this.settings.player.enablePlaybackRangeSelection || this.settings.player.enableSeekToClick) e.preventDefault();
48623
48755
  const relX = e.getX(this.canvasElement);
48624
48756
  const relY = e.getY(this.canvasElement);
48625
48757
  const beat = this._renderer.boundsLookup?.getBeatAtPos(relX, relY) ?? null;
@@ -48646,7 +48778,7 @@
48646
48778
  });
48647
48779
  this.canvasElement.mouseUp.on((e) => {
48648
48780
  if (!this._isBeatMouseDown) return;
48649
- if (this.settings.player.enableUserInteraction) e.preventDefault();
48781
+ if (this.settings.player.enablePlaybackRangeSelection || this.settings.player.enableSeekToClick) e.preventDefault();
48650
48782
  const relX = e.getX(this.canvasElement);
48651
48783
  const relY = e.getY(this.canvasElement);
48652
48784
  const beat = this._renderer.boundsLookup?.getBeatAtPos(relX, relY) ?? null;
@@ -48657,7 +48789,7 @@
48657
48789
  } else this._onNoteMouseUp(e, null);
48658
48790
  });
48659
48791
  this._renderer.postRenderFinished.on(() => {
48660
- if (!this._selectionStart || !this._hasCursor || !this.settings.player.enableUserInteraction) return;
48792
+ if (!this._selectionStart || !this._hasCursor || !this.settings.player.enablePlaybackRangeSelection) return;
48661
48793
  this._cursorSelectRange(this._selectionStart, this._selectionEnd);
48662
48794
  });
48663
48795
  }
@@ -48749,6 +48881,9 @@
48749
48881
  * ```
48750
48882
  */
48751
48883
  applyPlaybackRangeFromHighlight() {
48884
+ this._internalApplyPlaybackRangeFromHighlight();
48885
+ }
48886
+ _internalApplyPlaybackRangeFromHighlight() {
48752
48887
  if (this._selectionEnd) {
48753
48888
  const startTick = this._tickCache?.getBeatStart(this._selectionStart.beat) ?? this._selectionStart.beat.absolutePlaybackStart;
48754
48889
  if ((this._tickCache?.getBeatStart(this._selectionEnd.beat) ?? this._selectionEnd.beat.absolutePlaybackStart) < startTick) {
@@ -48756,27 +48891,32 @@
48756
48891
  this._selectionStart = this._selectionEnd;
48757
48892
  this._selectionEnd = t;
48758
48893
  }
48759
- }
48894
+ } else if (!this.settings.player.resetPlaybackRangeOnClick) return false;
48760
48895
  if (this._selectionStart && this._tickCache) {
48761
48896
  const tickCache = this._tickCache;
48762
48897
  const realStartMasterBarStart = tickCache.getMasterBarStart(this._selectionStart.beat.voice.bar.masterBar);
48763
48898
  const startBeatPlaybackStart = tickCache.getRelativeBeatPlaybackRange(this._selectionStart.beat)?.startTick ?? this._selectionStart.beat.playbackStart;
48764
- this._currentBeat = null;
48765
- if (this._player.state === PlayerState.Paused) this._cursorUpdateTick(realStartMasterBarStart + startBeatPlaybackStart, false, 1);
48766
- this.tickPosition = realStartMasterBarStart + startBeatPlaybackStart;
48899
+ let seekToStart = this.settings.player.enableSeekToClick;
48767
48900
  if (this._selectionEnd && this._selectionStart.beat !== this._selectionEnd.beat) {
48901
+ seekToStart = true;
48768
48902
  const realEndMasterBarStart = tickCache.getMasterBarStart(this._selectionEnd.beat.voice.bar.masterBar);
48769
48903
  const endBeatPlaybackEnd = tickCache.getRelativeBeatPlaybackRange(this._selectionEnd.beat)?.endTick ?? this._selectionEnd.beat.playbackStart + this._selectionEnd.beat.playbackDuration;
48770
48904
  const range = new PlaybackRange();
48771
48905
  range.startTick = realStartMasterBarStart + startBeatPlaybackStart;
48772
48906
  range.endTick = realEndMasterBarStart + endBeatPlaybackEnd - 50;
48773
48907
  this.playbackRange = range;
48774
- } else {
48908
+ } else if (this.settings.player.resetPlaybackRangeOnClick) {
48775
48909
  this._selectionStart = void 0;
48776
48910
  this.playbackRange = null;
48777
48911
  this._cursorSelectRange(this._selectionStart, this._selectionEnd);
48778
48912
  }
48913
+ if (seekToStart) {
48914
+ this._currentBeat = null;
48915
+ if (this._player.state === PlayerState.Paused) this._cursorUpdateTick(realStartMasterBarStart + startBeatPlaybackStart, false, 1);
48916
+ this.tickPosition = realStartMasterBarStart + startBeatPlaybackStart;
48917
+ }
48779
48918
  }
48919
+ return true;
48780
48920
  }
48781
48921
  /**
48782
48922
  * Clears the highlight markers marking the currently selected playback range.
@@ -50062,7 +50202,8 @@
50062
50202
  settings.player.enableCursor = false;
50063
50203
  settings.player.playerMode = PlayerMode.Disabled;
50064
50204
  settings.player.enableElementHighlighting = false;
50065
- settings.player.enableUserInteraction = false;
50205
+ settings.player.enableSeekToClick = false;
50206
+ settings.player.enablePlaybackRangeSelection = false;
50066
50207
  settings.player.soundFont = null;
50067
50208
  settings.display.scale = .8;
50068
50209
  settings.display.stretchForce = .8;
@@ -50872,7 +51013,9 @@
50872
51013
  }
50873
51014
  handleMessage(e) {
50874
51015
  const data = e.data;
50875
- switch (data.cmd) {
51016
+ const cmd = data.cmd;
51017
+ if (!cmd) return;
51018
+ switch (cmd) {
50876
51019
  case "alphaSynth.initialize":
50877
51020
  AlphaSynthWorkerSynthOutput.preferredSampleRate = data.sampleRate;
50878
51021
  Logger.logLevel = data.logLevel;
@@ -50966,7 +51109,7 @@
50966
51109
  this._player.applyTranspositionPitches(data.transpositionPitches);
50967
51110
  break;
50968
51111
  }
50969
- if (data.cmd.startsWith("alphaSynth.exporter")) this._handleExporterMessage(e);
51112
+ if (cmd.startsWith("alphaSynth.exporter")) this._handleExporterMessage(e);
50970
51113
  }
50971
51114
  _handleExporterMessage(ev) {
50972
51115
  const data = ev.data;
@@ -54470,9 +54613,35 @@
54470
54613
  const force = this.renderer.layoutingInfo.spaceToForce(width);
54471
54614
  this._scaleToForce(force, true);
54472
54615
  }
54616
+ /**
54617
+ * `true` when every voice/track/staff contributes exactly one beat, of uniform duration,
54618
+ * spanning the bar's entire duration - i.e. a single full-bar note/rest. Common engraving
54619
+ * practice centers such notes horizontally within the bar rather than anchoring them right
54620
+ * after the pre-beat content (Behind Bars, p. 41; see #2464).
54621
+ */
54622
+ _isCenteredFullBar() {
54623
+ const masterBar = this.renderer.bar.masterBar;
54624
+ const layoutingInfo = this.renderer.layoutingInfo;
54625
+ const springs = layoutingInfo.springs;
54626
+ if (springs.size !== 1 || !springs.has(masterBar.start) || layoutingInfo.allGraceRods.size > 0) return false;
54627
+ const spring = springs.get(masterBar.start);
54628
+ return spring.allDurations.size === 1 && spring.longestDuration === masterBar.calculateDuration();
54629
+ }
54473
54630
  /** `emit=false`: positioning-only path; final skyline emission runs later via {@link scaleToWidth}. */
54474
54631
  _scaleToForce(force, emit) {
54475
54632
  this.width = this.renderer.layoutingInfo.calculateVoiceWidth(force);
54633
+ if (this._isCenteredFullBar()) {
54634
+ const barNumberWidth = this.renderer.barNumberWidth;
54635
+ const target = (this.width - barNumberWidth) / 2;
54636
+ for (const beatGlyphs of this.beatGlyphs.values()) {
54637
+ const soleBeatGlyph = beatGlyphs[0];
54638
+ soleBeatGlyph.x = 0;
54639
+ soleBeatGlyph.applyCenterOffset(target);
54640
+ soleBeatGlyph.scaleToWidth(this.width);
54641
+ if (emit) this._emitBeatContainerSkyline(soleBeatGlyph);
54642
+ }
54643
+ return;
54644
+ }
54476
54645
  const positions = this.renderer.layoutingInfo.buildOnTimePositions(force);
54477
54646
  for (const beatGlyphs of this.beatGlyphs.values()) for (let i = 0, j = beatGlyphs.length; i < j; i++) {
54478
54647
  const currentBeatGlyph = beatGlyphs[i];
@@ -60794,14 +60963,22 @@
60794
60963
  calculateBeamY(h, x) {
60795
60964
  return this.calculateBeamYWithDirection(h, x, this.getBeamDirection(h));
60796
60965
  }
60966
+ barNumberGlyph;
60967
+ get barNumberWidth() {
60968
+ return this.barNumberGlyph?.width ?? 0;
60969
+ }
60797
60970
  createPreBeatGlyphs() {
60798
60971
  super.createPreBeatGlyphs();
60972
+ this.barNumberGlyph = void 0;
60799
60973
  this.addPreBeatGlyph(new BarLineGlyph(false, this.bar.staff.track.score.stylesheet.extendBarLines));
60800
60974
  this.createLinePreBeatGlyphs();
60801
60975
  let hasSpaceAfterStartGlyphs = false;
60802
60976
  if (this.index === 0) hasSpaceAfterStartGlyphs = this.createStartSpacing();
60803
- if (this.shouldCreateBarNumber()) this.addPreBeatGlyph(new BarNumberGlyph(0, this.getLineHeight(-.5), this.bar.index + 1));
60804
- else if (!hasSpaceAfterStartGlyphs) this.addPreBeatGlyph(new SpacingGlyph(0, 0, this.smuflMetrics.oneStaffSpace));
60977
+ if (this.shouldCreateBarNumber()) {
60978
+ const barNumberGlyph = new BarNumberGlyph(0, this.getLineHeight(-.5), this.bar.index + 1);
60979
+ this.barNumberGlyph = barNumberGlyph;
60980
+ this.addPreBeatGlyph(barNumberGlyph);
60981
+ } else if (!hasSpaceAfterStartGlyphs) this.addPreBeatGlyph(new SpacingGlyph(0, 0, this.smuflMetrics.oneStaffSpace));
60805
60982
  }
60806
60983
  resolveClefDisplay() {
60807
60984
  return { isVisible: false };
@@ -64393,8 +64570,11 @@
64393
64570
  if (this.index === 0 || this.bar.masterBar.isRepeatStart && this.staff.isCascadePrimary) this.addPreBeatGlyph(new BarLineGlyph(false, this.bar.staff.track.score.stylesheet.extendBarLines));
64394
64571
  this.createLinePreBeatGlyphs();
64395
64572
  const hasSpaceAfterStartGlyphs = this.createStartSpacing();
64396
- if (this.shouldCreateBarNumber()) this.addPreBeatGlyph(new BarNumberGlyph(0, this.getLineHeight(-.5), this.bar.index + 1));
64397
- else if (!hasSpaceAfterStartGlyphs) this.addPreBeatGlyph(new SpacingGlyph(0, 0, this.smuflMetrics.oneStaffSpace));
64573
+ if (this.shouldCreateBarNumber()) {
64574
+ const barNumberGlyph = new BarNumberGlyph(0, this.getLineHeight(-.5), this.bar.index + 1);
64575
+ this.barNumberGlyph = barNumberGlyph;
64576
+ this.addPreBeatGlyph(barNumberGlyph);
64577
+ } else if (!hasSpaceAfterStartGlyphs) this.addPreBeatGlyph(new SpacingGlyph(0, 0, this.smuflMetrics.oneStaffSpace));
64398
64578
  }
64399
64579
  createLinePreBeatGlyphs() {
64400
64580
  const timeSignatureDisplay = this.resolveTimeSignatureDisplay();
@@ -70039,8 +70219,8 @@
70039
70219
  scoreNode.addElement("FirstPageFooter").setCData("");
70040
70220
  scoreNode.addElement("PageHeader").setCData("");
70041
70221
  scoreNode.addElement("PageFooter").setCData("");
70042
- scoreNode.addElement("ScoreSystemsDefaultLayout").setCData(score.defaultSystemsLayout.toString());
70043
- scoreNode.addElement("ScoreSystemsLayout").setCData(score.systemsLayout.join(" "));
70222
+ scoreNode.addElement("ScoreSystemsDefaultLayout").innerText = score.defaultSystemsLayout.toString();
70223
+ scoreNode.addElement("ScoreSystemsLayout").innerText = score.systemsLayout.join(" ");
70044
70224
  scoreNode.addElement("ScoreZoomPolicy").innerText = "Value";
70045
70225
  scoreNode.addElement("ScoreZoom").innerText = "1";
70046
70226
  scoreNode.addElement("MultiVoice").innerText = "1>";