pxt-core 8.2.1 → 8.2.4

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/built/pxtlib.js CHANGED
@@ -8713,10 +8713,10 @@ var pxt;
8713
8713
  docs.prepTemplate = prepTemplate;
8714
8714
  function setupRenderer(renderer) {
8715
8715
  renderer.image = function (href, title, text) {
8716
- const endpointName = "makecode-lucas-testing-makecodetempmediaservice-usea";
8716
+ const endpointName = "makecodeprodmediaeastus-usea";
8717
8717
  if (href.startsWith("youtube:")) {
8718
- let out = '<div class="tutorial-video-embed"><iframe src="https://www.youtube.com/embed/' + href.split(":").pop()
8719
- + '" title="' + title + '" frameborder="0" ' + 'allowFullScreen ' + 'allow="autoplay; picture-in-picture"></iframe></div>';
8718
+ let out = '<div class="tutorial-video-embed"><iframe class="yt-embed" src="https://www.youtube.com/embed/' + href.split(":").pop()
8719
+ + '" title="' + text + '" frameborder="0" ' + 'allowFullScreen ' + 'allow="autoplay; picture-in-picture"></iframe></div>';
8720
8720
  return out;
8721
8721
  }
8722
8722
  else if (href.startsWith("azuremedia:")) {
@@ -10500,14 +10500,17 @@ var pxt;
10500
10500
  return false;
10501
10501
  }
10502
10502
  function isRepoBanned(repo, config) {
10503
+ var _a, _b;
10503
10504
  if (isOrgBanned(repo, config))
10504
10505
  return true;
10505
10506
  if (!config)
10506
10507
  return false; // don't know
10507
- if (!repo || !repo.fullName)
10508
+ if (!repo)
10508
10509
  return true;
10510
+ const repoFull = (_a = repo.fullName) === null || _a === void 0 ? void 0 : _a.toLowerCase();
10511
+ const repoSlug = (_b = repo.slug) === null || _b === void 0 ? void 0 : _b.toLowerCase();
10509
10512
  if (config.bannedRepos
10510
- && config.bannedRepos.some(fn => fn.toLowerCase() == repo.fullName.toLowerCase()))
10513
+ && config.bannedRepos.some(fn => fn && (fn.toLowerCase() == repoFull || fn.toLowerCase() == repoSlug)))
10511
10514
  return true;
10512
10515
  return false;
10513
10516
  }
@@ -10521,13 +10524,15 @@ var pxt;
10521
10524
  return false;
10522
10525
  }
10523
10526
  function isRepoApproved(repo, config) {
10524
- var _a;
10527
+ var _a, _b;
10525
10528
  if (isOrgApproved(repo, config))
10526
10529
  return true;
10527
- if (!repo || !config)
10530
+ const repoFull = (_a = repo === null || repo === void 0 ? void 0 : repo.fullName) === null || _a === void 0 ? void 0 : _a.toLowerCase();
10531
+ const repoSlug = (_b = repo === null || repo === void 0 ? void 0 : repo.slug) === null || _b === void 0 ? void 0 : _b.toLowerCase();
10532
+ if (!(config === null || config === void 0 ? void 0 : config.approvedRepoLib) || !(repoFull || repoSlug))
10528
10533
  return false;
10529
- if (repo.fullName
10530
- && ((_a = config.approvedRepoLib) === null || _a === void 0 ? void 0 : _a[repo.fullName.toLowerCase()]))
10534
+ if (config.approvedRepoLib[repoFull]
10535
+ || config.approvedRepoLib[repoSlug])
10531
10536
  return true;
10532
10537
  return false;
10533
10538
  }
@@ -16905,6 +16910,97 @@ var pxt;
16905
16910
  return outParts.join(" ");
16906
16911
  }
16907
16912
  }
16913
+ function soundToInstructionBuffer(sound, fxSteps, fxRange) {
16914
+ const { startFrequency, endFrequency, startVolume, endVolume, interpolation, duration } = sound;
16915
+ const steps = [];
16916
+ // Optimize the simple case
16917
+ if (sound.interpolation === "linear" && sound.effect === "none") {
16918
+ steps.push({
16919
+ frequency: startFrequency,
16920
+ volume: (startVolume / assets.MAX_VOLUME) * 1024,
16921
+ });
16922
+ steps.push({
16923
+ frequency: endFrequency,
16924
+ volume: (endVolume / assets.MAX_VOLUME) * 1024,
16925
+ });
16926
+ }
16927
+ else {
16928
+ fxSteps = Math.min(fxSteps, Math.floor(duration / 5));
16929
+ const getVolumeAt = (t) => ((startVolume + t * (endVolume - startVolume) / duration) / assets.MAX_VOLUME) * 1024;
16930
+ let getFrequencyAt;
16931
+ switch (interpolation) {
16932
+ case "linear":
16933
+ getFrequencyAt = t => startFrequency + t * (endFrequency - startFrequency) / duration;
16934
+ break;
16935
+ case "curve":
16936
+ getFrequencyAt = t => startFrequency + (endFrequency - startFrequency) * Math.sin(t / duration * (Math.PI / 2));
16937
+ break;
16938
+ case "logarithmic":
16939
+ getFrequencyAt = t => startFrequency + Math.log10(1 + 9 * (t / duration)) * (endFrequency - startFrequency);
16940
+ break;
16941
+ }
16942
+ const timeSlice = duration / fxSteps;
16943
+ for (let i = 0; i < fxSteps; i++) {
16944
+ const newStep = {
16945
+ frequency: Math.max(getFrequencyAt(i * timeSlice), 1),
16946
+ volume: getVolumeAt(i * timeSlice)
16947
+ };
16948
+ if (sound.effect === "tremolo") {
16949
+ if (i % 2 === 0) {
16950
+ newStep.volume = Math.max(newStep.volume - fxRange * 500, 0);
16951
+ }
16952
+ else {
16953
+ newStep.volume = Math.min(newStep.volume + fxRange * 500, 1023);
16954
+ }
16955
+ }
16956
+ else if (sound.effect === "vibrato") {
16957
+ if (i % 2 === 0) {
16958
+ newStep.frequency = Math.max(newStep.frequency - fxRange * 100, 1);
16959
+ }
16960
+ else {
16961
+ newStep.frequency = newStep.frequency + fxRange * 100;
16962
+ }
16963
+ }
16964
+ else if (sound.effect === "warble") {
16965
+ if (i % 2 === 0) {
16966
+ newStep.frequency = Math.max(newStep.frequency - fxRange * 1000, 1);
16967
+ }
16968
+ else {
16969
+ newStep.frequency = newStep.frequency + fxRange * 1000;
16970
+ }
16971
+ }
16972
+ steps.push(newStep);
16973
+ }
16974
+ }
16975
+ const out = new Uint8Array(12 * (steps.length - 1));
16976
+ const stepDuration = Math.floor(duration / (steps.length - 1));
16977
+ for (let i = 0; i < steps.length - 1; i++) {
16978
+ const offset = i * 12;
16979
+ out[offset] = waveToValue(sound.wave);
16980
+ set16BitNumber(out, offset + 2, steps[i].frequency);
16981
+ set16BitNumber(out, offset + 4, stepDuration);
16982
+ set16BitNumber(out, offset + 6, steps[i].volume);
16983
+ set16BitNumber(out, offset + 8, steps[i + 1].volume);
16984
+ set16BitNumber(out, offset + 10, steps[i + 1].frequency);
16985
+ }
16986
+ return out;
16987
+ }
16988
+ assets.soundToInstructionBuffer = soundToInstructionBuffer;
16989
+ function waveToValue(wave) {
16990
+ switch (wave) {
16991
+ case "square": return 15;
16992
+ case "sine": return 3;
16993
+ case "triangle": return 1;
16994
+ case "noise": return 18;
16995
+ case "sawtooth": return 2;
16996
+ }
16997
+ }
16998
+ function set16BitNumber(buf, offset, value) {
16999
+ const temp = new Uint8Array(2);
17000
+ new Uint16Array(temp.buffer)[0] = value | 0;
17001
+ buf[offset] = temp[0];
17002
+ buf[offset + 1] = temp[1];
17003
+ }
16908
17004
  })(assets = pxt.assets || (pxt.assets = {}));
16909
17005
  })(pxt || (pxt = {}));
16910
17006
  // See https://github.com/microsoft/TouchDevelop-backend/blob/master/docs/streams.md
@@ -97,6 +97,7 @@ declare namespace pxt.runner {
97
97
  dependencies?: string[];
98
98
  builtJsInfo?: pxtc.BuiltSimJsInfo;
99
99
  single?: boolean;
100
+ hideSimButtons?: boolean;
100
101
  autofocus?: boolean;
101
102
  }
102
103
  let mainPkg: pxt.MainPackage;
@@ -1750,6 +1750,7 @@ var pxt;
1750
1750
  storedState: storedState,
1751
1751
  light: simOptions.light,
1752
1752
  single: simOptions.single,
1753
+ hideSimButtons: simOptions.hideSimButtons,
1753
1754
  autofocus: simOptions.autofocus
1754
1755
  };
1755
1756
  if (pxt.appTarget.simulator && !simOptions.fullScreen)
package/built/pxtsim.d.ts CHANGED
@@ -1268,6 +1268,7 @@ declare namespace pxsim {
1268
1268
  ipc?: boolean;
1269
1269
  dependencies?: Map<string>;
1270
1270
  single?: boolean;
1271
+ hideSimButtons?: boolean;
1271
1272
  autofocus?: boolean;
1272
1273
  }
1273
1274
  interface HwDebugger {
@@ -1423,11 +1424,11 @@ declare namespace pxsim {
1423
1424
  function frequency(): number;
1424
1425
  function muteAllChannels(): void;
1425
1426
  function queuePlayInstructions(when: number, b: RefBuffer): void;
1426
- function playInstructionsAsync(b: RefBuffer): Promise<void>;
1427
1427
  function tone(frequency: number, gain: number): void;
1428
1428
  function setCurrentToneGain(gain: number): void;
1429
1429
  function playBufferAsync(buf: RefBuffer): Promise<void>;
1430
1430
  function playPCMBufferStreamAsync(pull: () => Float32Array, sampleRate: number, volume?: number, isCancelled?: () => boolean): Promise<void>;
1431
+ function playInstructionsAsync(instructions: Uint8Array, isCancelled?: () => boolean, onPull?: (freq: number, volume: number) => void): Promise<void>;
1431
1432
  function sendMidiMessage(buf: RefBuffer): void;
1432
1433
  }
1433
1434
  interface IPointerEvents {
package/built/pxtsim.js CHANGED
@@ -6295,7 +6295,7 @@ var pxsim;
6295
6295
  }
6296
6296
  }
6297
6297
  createFrame(url) {
6298
- var _a;
6298
+ var _a, _b;
6299
6299
  const wrapper = document.createElement("div");
6300
6300
  wrapper.className = `simframe ui embed`;
6301
6301
  const frame = document.createElement('iframe');
@@ -6305,12 +6305,18 @@ var pxsim;
6305
6305
  frame.setAttribute('allow', 'autoplay;microphone');
6306
6306
  frame.setAttribute('sandbox', 'allow-same-origin allow-scripts');
6307
6307
  frame.className = 'no-select';
6308
- const furl = (url || this.getSimUrl()) + '#' + frame.id;
6308
+ let furl = url || this.getSimUrl().toString();
6309
+ if ((_a = this._runOptions) === null || _a === void 0 ? void 0 : _a.hideSimButtons) {
6310
+ const urlObject = new URL(furl);
6311
+ urlObject.searchParams.append("hideSimButtons", "1");
6312
+ furl = urlObject.toString();
6313
+ }
6314
+ furl += '#' + frame.id;
6309
6315
  frame.src = furl;
6310
6316
  frame.frameBorder = "0";
6311
6317
  frame.dataset['runid'] = this.runId;
6312
6318
  frame.dataset['origin'] = new URL(furl).origin || "*";
6313
- if ((_a = this._runOptions) === null || _a === void 0 ? void 0 : _a.autofocus)
6319
+ if ((_b = this._runOptions) === null || _b === void 0 ? void 0 : _b.autofocus)
6314
6320
  frame.setAttribute("autofocus", "true");
6315
6321
  wrapper.appendChild(frame);
6316
6322
  const i = document.createElement("i");
@@ -6547,8 +6553,7 @@ var pxsim;
6547
6553
  msg.frameCounter = ++this.frameCounter;
6548
6554
  msg.options = {
6549
6555
  theme: this.themes[this.nextFrameId++ % this.themes.length],
6550
- mpRole: (_b = (_a = /[\&\?]mp=(server|client)/i.exec(window.location.href)) === null || _a === void 0 ? void 0 : _a[1]) === null || _b === void 0 ? void 0 : _b.toLowerCase(),
6551
- hideSimButtons: /hidesimbuttons(?:[:=])1/i.test(window.location.href)
6556
+ mpRole: (_b = (_a = /[\&\?]mp=(server|client)/i.exec(window.location.href)) === null || _a === void 0 ? void 0 : _a[1]) === null || _b === void 0 ? void 0 : _b.toLowerCase()
6552
6557
  };
6553
6558
  msg.id = `${msg.options.theme}-${this.nextId()}`;
6554
6559
  frame.dataset['runid'] = this.runId;
@@ -7245,92 +7250,10 @@ var pxsim;
7245
7250
  .then(() => {
7246
7251
  if (prevStop != instrStopId)
7247
7252
  return Promise.resolve();
7248
- return playInstructionsAsync(b);
7253
+ return playInstructionsAsync(b.data);
7249
7254
  });
7250
7255
  }
7251
7256
  AudioContextManager.queuePlayInstructions = queuePlayInstructions;
7252
- function playInstructionsAsync(b) {
7253
- const prevStop = instrStopId;
7254
- let ctx = context();
7255
- let idx = 0;
7256
- let ch = new Channel();
7257
- let currWave = -1;
7258
- let currFreq = -1;
7259
- let timeOff = 0;
7260
- if (channels.length > 5)
7261
- channels[0].remove();
7262
- channels.push(ch);
7263
- /** Square waves are perceved as much louder than other sounds, so scale it down a bit to make it less jarring **/
7264
- const scaleVol = (n, isSqWave) => (n / 1024) / 4 * (isSqWave ? .5 : 1);
7265
- const finish = () => {
7266
- ch.disconnectNodes();
7267
- timeOff = 0;
7268
- currWave = -1;
7269
- currFreq = -1;
7270
- };
7271
- const loopAsync = () => {
7272
- if (idx >= b.data.length || !b.data[idx])
7273
- return pxsim.U.delay(timeOff).then(finish);
7274
- const soundWaveIdx = b.data[idx];
7275
- const freq = pxsim.BufferMethods.getNumber(b, pxsim.BufferMethods.NumberFormat.UInt16LE, idx + 2);
7276
- const duration = pxsim.BufferMethods.getNumber(b, pxsim.BufferMethods.NumberFormat.UInt16LE, idx + 4);
7277
- const startVol = pxsim.BufferMethods.getNumber(b, pxsim.BufferMethods.NumberFormat.UInt16LE, idx + 6);
7278
- const endVol = pxsim.BufferMethods.getNumber(b, pxsim.BufferMethods.NumberFormat.UInt16LE, idx + 8);
7279
- const endFreq = pxsim.BufferMethods.getNumber(b, pxsim.BufferMethods.NumberFormat.UInt16LE, idx + 10);
7280
- const isSquareWave = 11 <= soundWaveIdx && soundWaveIdx <= 15;
7281
- const isFilteredNoise = soundWaveIdx == 4 || (16 <= soundWaveIdx && soundWaveIdx <= 18);
7282
- const scaledStart = scaleVol(startVol, isSquareWave);
7283
- const scaledEnd = scaleVol(endVol, isSquareWave);
7284
- if (!ctx || prevStop != instrStopId)
7285
- return pxsim.U.delay(duration);
7286
- if (currWave != soundWaveIdx || currFreq != freq || freq != endFreq) {
7287
- if (ch.generator) {
7288
- return pxsim.U.delay(timeOff)
7289
- .then(() => {
7290
- finish();
7291
- return loopAsync();
7292
- });
7293
- }
7294
- ch.generator = getGenerator(soundWaveIdx, freq);
7295
- if (!ch.generator)
7296
- return pxsim.U.delay(duration);
7297
- currWave = soundWaveIdx;
7298
- currFreq = freq;
7299
- ch.gain = ctx.createGain();
7300
- ch.gain.gain.value = 0;
7301
- ch.gain.gain.setTargetAtTime(scaledStart, _context.currentTime, 0.015);
7302
- if (endFreq != freq) {
7303
- if (ch.generator.frequency != undefined) {
7304
- // If generator is an OscillatorNode
7305
- const param = ch.generator.frequency;
7306
- param.linearRampToValueAtTime(endFreq, ctx.currentTime + ((timeOff + duration) / 1000));
7307
- }
7308
- else if (ch.generator.playbackRate != undefined) {
7309
- // If generator is an AudioBufferSourceNode
7310
- const param = ch.generator.playbackRate;
7311
- const bufferSamplesPerWave = isFilteredNoise ? 4 : 1024;
7312
- param.linearRampToValueAtTime(endFreq / (context().sampleRate / bufferSamplesPerWave), ctx.currentTime + ((timeOff + duration) / 1000));
7313
- }
7314
- }
7315
- ch.generator.connect(ch.gain);
7316
- ch.gain.connect(destination);
7317
- ch.generator.start();
7318
- }
7319
- idx += 12;
7320
- ch.gain.gain.setValueAtTime(scaledStart, ctx.currentTime + (timeOff / 1000));
7321
- timeOff += duration;
7322
- // To prevent clipping, we ramp to this value slightly earlier than intended. This is so that we
7323
- // can go for a smooth ramp to 0 in ch.mute() without this operation interrupting it. If we had
7324
- // more accurate timing this would not be necessary, but we'd probably have to do something like
7325
- // running a metronome in a webworker to get the level of precision we need
7326
- const endTime = scaledEnd !== 0 && duration > 50 ? ((timeOff - 50) / 1000) : ((timeOff - 10) / 1000);
7327
- ch.gain.gain.linearRampToValueAtTime(scaledEnd, ctx.currentTime + endTime);
7328
- return loopAsync();
7329
- };
7330
- return loopAsync()
7331
- .then(() => ch.remove());
7332
- }
7333
- AudioContextManager.playInstructionsAsync = playInstructionsAsync;
7334
7257
  function tone(frequency, gain) {
7335
7258
  if (frequency < 0)
7336
7259
  return;
@@ -7469,6 +7392,126 @@ var pxsim;
7469
7392
  function frequencyFromMidiNoteNumber(note) {
7470
7393
  return 440 * Math.pow(2, (note - 69) / 12);
7471
7394
  }
7395
+ function playInstructionsAsync(instructions, isCancelled, onPull) {
7396
+ return new Promise(async (resolve) => {
7397
+ let resolved = false;
7398
+ let ctx = context();
7399
+ let channel = new Channel();
7400
+ if (channels.length > 5)
7401
+ channels[0].remove();
7402
+ channels.push(channel);
7403
+ channel.gain = ctx.createGain();
7404
+ channel.gain.gain.value = 1;
7405
+ channel.gain.connect(destination);
7406
+ const oscillators = {};
7407
+ const gains = {};
7408
+ let startTime = ctx.currentTime;
7409
+ let currentTime = startTime;
7410
+ let currentWave = 0;
7411
+ let totalDuration = 0;
7412
+ /** Square waves are perceved as much louder than other sounds, so scale it down a bit to make it less jarring **/
7413
+ const scaleVol = (n, isSqWave) => (n / 1024) / 4 * (isSqWave ? .5 : 1);
7414
+ const disconnectNodes = () => {
7415
+ if (resolved)
7416
+ return;
7417
+ resolved = true;
7418
+ channel.disconnectNodes();
7419
+ for (const wave of Object.keys(oscillators)) {
7420
+ oscillators[wave].stop();
7421
+ oscillators[wave].disconnect();
7422
+ gains[wave].disconnect();
7423
+ }
7424
+ resolve();
7425
+ };
7426
+ for (let i = 0; i < instructions.length; i += 12) {
7427
+ const wave = instructions[i];
7428
+ const startFrequency = readUint16(instructions, i + 2);
7429
+ const duration = readUint16(instructions, i + 4) / 1000;
7430
+ const startVolume = readUint16(instructions, i + 6);
7431
+ const endVolume = readUint16(instructions, i + 8);
7432
+ const endFrequency = readUint16(instructions, i + 10);
7433
+ totalDuration += duration;
7434
+ const isSquareWave = 11 <= wave && wave <= 15;
7435
+ if (!oscillators[wave]) {
7436
+ oscillators[wave] = getGenerator(wave, startFrequency);
7437
+ gains[wave] = ctx.createGain();
7438
+ gains[wave].gain.value = 0;
7439
+ gains[wave].connect(channel.gain);
7440
+ oscillators[wave].connect(gains[wave]);
7441
+ oscillators[wave].start();
7442
+ }
7443
+ if (currentWave && wave !== currentWave) {
7444
+ gains[currentWave].gain.setTargetAtTime(0, currentTime, 0.015);
7445
+ }
7446
+ const osc = oscillators[wave];
7447
+ const gain = gains[wave];
7448
+ if (osc instanceof OscillatorNode) {
7449
+ osc.frequency.setValueAtTime(startFrequency, currentTime);
7450
+ osc.frequency.linearRampToValueAtTime(endFrequency, currentTime + duration);
7451
+ }
7452
+ else {
7453
+ const isFilteredNoise = wave == 4 || (16 <= wave && wave <= 18);
7454
+ if (isFilteredNoise)
7455
+ osc.playbackRate.linearRampToValueAtTime(endFrequency / (ctx.sampleRate / 4), currentTime + duration);
7456
+ else if (wave != 5)
7457
+ osc.playbackRate.linearRampToValueAtTime(endFrequency / (ctx.sampleRate / 1024), currentTime + duration);
7458
+ }
7459
+ gain.gain.setValueAtTime(scaleVol(startVolume, isSquareWave), currentTime);
7460
+ gain.gain.linearRampToValueAtTime(scaleVol(endVolume, isSquareWave), currentTime + duration);
7461
+ currentWave = wave;
7462
+ currentTime += duration;
7463
+ }
7464
+ channel.gain.gain.setTargetAtTime(0, currentTime, 0.015);
7465
+ if (isCancelled || onPull) {
7466
+ const handleAnimationFrame = () => {
7467
+ const time = ctx.currentTime;
7468
+ if (time > startTime + totalDuration) {
7469
+ return;
7470
+ }
7471
+ if (isCancelled && isCancelled()) {
7472
+ disconnectNodes();
7473
+ return;
7474
+ }
7475
+ const { frequency, volume } = findFrequencyAndVolumeAtTime((time - startTime) * 1000, instructions);
7476
+ onPull(frequency, volume / 1024);
7477
+ requestAnimationFrame(handleAnimationFrame);
7478
+ };
7479
+ requestAnimationFrame(handleAnimationFrame);
7480
+ }
7481
+ await pxsim.U.delay(totalDuration * 1000);
7482
+ disconnectNodes();
7483
+ });
7484
+ }
7485
+ AudioContextManager.playInstructionsAsync = playInstructionsAsync;
7486
+ function readUint16(buf, offset) {
7487
+ const temp = new Uint8Array(2);
7488
+ temp[0] = buf[offset];
7489
+ temp[1] = buf[offset + 1];
7490
+ return new Uint16Array(temp.buffer)[0];
7491
+ }
7492
+ function findFrequencyAndVolumeAtTime(millis, instructions) {
7493
+ let currentTime = 0;
7494
+ for (let i = 0; i < instructions.length; i += 12) {
7495
+ const startFrequency = readUint16(instructions, i + 2);
7496
+ const duration = readUint16(instructions, i + 4);
7497
+ const startVolume = readUint16(instructions, i + 6);
7498
+ const endVolume = readUint16(instructions, i + 8);
7499
+ const endFrequency = readUint16(instructions, i + 10);
7500
+ if (currentTime + duration < millis) {
7501
+ currentTime += duration;
7502
+ continue;
7503
+ }
7504
+ const offset = (millis - currentTime) / duration;
7505
+ return {
7506
+ frequency: startFrequency + (endFrequency - startFrequency) * offset,
7507
+ volume: startVolume + (endVolume - startVolume) * offset,
7508
+ };
7509
+ }
7510
+ return {
7511
+ frequency: -1,
7512
+ volume: -1
7513
+ };
7514
+ }
7472
7515
  function sendMidiMessage(buf) {
7473
7516
  const data = buf.data;
7474
7517
  if (!data.length) // garbage.