pxt-microbit 5.1.25 → 5.1.27

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/editor.js CHANGED
@@ -3967,7 +3967,7 @@ exports.mkDAPLinkPacketIOWrapper = mkDAPLinkPacketIOWrapper;
3967
3967
  <field name="LED34">FALSE</field>
3968
3968
  <field name="LED44">FALSE</field>
3969
3969
  </block>
3970
-
3970
+
3971
3971
  to
3972
3972
  <block type="device_show_leds">
3973
3973
  <field name="LEDS">`
@@ -3983,6 +3983,37 @@ exports.mkDAPLinkPacketIOWrapper = mkDAPLinkPacketIOWrapper;
3983
3983
  Object.defineProperty(exports, "__esModule", { value: true });
3984
3984
  exports.patchBlocks = void 0;
3985
3985
  function patchBlocks(pkgTargetVersion, dom) {
3986
+ if (pxt.semver.majorCmp(pkgTargetVersion || "0.0.0", "5.0.12") <= 0) {
3987
+ // Eighth note misspelling
3988
+ /*
3989
+ <block type="basic_show_icon">
3990
+ <field name="i">IconNames.EigthNote</field>
3991
+ </block>
3992
+
3993
+ converts to
3994
+
3995
+ <block type="basic_show_icon">
3996
+ <field name="i">IconNames.EighthNote</field>
3997
+ </block>
3998
+ */
3999
+ pxt.U.toArray(dom.querySelectorAll("block[type=basic_show_icon]>field[name=i]"))
4000
+ .filter(node => node.textContent === "IconNames.EigthNote")
4001
+ .forEach(node => node.textContent = "IconNames.EighthNote");
4002
+ // Italian translation error
4003
+ /*
4004
+ <shadow type="device_note">
4005
+ <field name="note">466</field>
4006
+ </shadow>
4007
+
4008
+ converts to
4009
+
4010
+ <shadow type="device_note">
4011
+ <field name="name">466</field>
4012
+ </shadow>
4013
+ */
4014
+ pxt.U.toArray(dom.querySelectorAll("shadow[type=device_note]>field[name=note]"))
4015
+ .forEach(node => node.setAttribute("name", "name"));
4016
+ }
3986
4017
  // is this a old script?
3987
4018
  if (pxt.semver.majorCmp(pkgTargetVersion || "0.0.0", "1.0.0") >= 0)
3988
4019
  return;
@@ -4030,9 +4061,9 @@ function patchBlocks(pkgTargetVersion, dom) {
4030
4061
  <mutation callbackproperties="receivedString" renamemap="{}"></mutation>
4031
4062
  <field name="receivedString">receivedString</field>
4032
4063
  </block>
4033
-
4064
+
4034
4065
  converts to
4035
-
4066
+
4036
4067
  <block type="radio_on_number" x="196" y="208">
4037
4068
  <field name="HANDLER_receivedNumber" id="DCy(W;1)*jLWQUpoy4Mm" variabletype="">receivedNumber</field>
4038
4069
  </block>
package/built/sim.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  /// <reference path="../libs/core/dal.d.ts" />
2
2
  /// <reference path="../libs/core/enums.d.ts" />
3
+ /// <reference types="dom-mediacapture-record" />
3
4
  declare namespace pxsim {
4
5
  interface CommonBoard extends CoreBoard, EventBusBoard {
5
6
  bus: EventBus;
@@ -564,6 +565,16 @@ declare namespace pxsim.music.MusicalProgressions {
564
565
  declare namespace pxsim {
565
566
  class RecordingState {
566
567
  currentlyRecording: boolean;
568
+ stream: MediaStream;
569
+ recorder: MediaRecorder;
570
+ chunks: Blob[];
571
+ audioURL: string;
572
+ recording: HTMLAudioElement;
573
+ audioPlaying: boolean;
574
+ recordTimeoutID: any;
575
+ handleAudioPlaying: () => void;
576
+ handleAudioStopped: () => void;
577
+ initListeners: () => void;
567
578
  }
568
579
  }
569
580
  declare namespace pxsim.record {
package/built/sim.js CHANGED
@@ -2278,6 +2278,19 @@ var pxsim;
2278
2278
  class RecordingState {
2279
2279
  constructor() {
2280
2280
  this.currentlyRecording = false;
2281
+ this.audioPlaying = false;
2282
+ this.handleAudioPlaying = () => {
2283
+ this.audioPlaying = true;
2284
+ };
2285
+ this.handleAudioStopped = () => {
2286
+ this.audioPlaying = false;
2287
+ };
2288
+ this.initListeners = () => {
2289
+ if (this.recording) {
2290
+ this.recording.addEventListener("play", this.handleAudioPlaying, false);
2291
+ this.recording.addEventListener("ended", this.handleAudioStopped, false);
2292
+ }
2293
+ };
2281
2294
  }
2282
2295
  }
2283
2296
  pxsim.RecordingState = RecordingState;
@@ -2285,59 +2298,116 @@ var pxsim;
2285
2298
  (function (pxsim) {
2286
2299
  var record;
2287
2300
  (function (record_1) {
2288
- let stream;
2289
- let recorder;
2290
- let chunks;
2291
- let audioURL;
2292
- let recording;
2293
- let audioPlaying = false;
2301
+ function stopRecorder(b) {
2302
+ b.recordingState.recorder.stop();
2303
+ b.recordingState.currentlyRecording = false;
2304
+ if (b.recordingState.stream.active) {
2305
+ b.recordingState.stream.getAudioTracks().forEach(track => {
2306
+ track.stop();
2307
+ track.enabled = false;
2308
+ });
2309
+ }
2310
+ }
2311
+ function populateRecording(b) {
2312
+ const blob = new Blob(b.recordingState.chunks, { type: "audio/ogg; codecs=opus" });
2313
+ b.recordingState.audioURL = window.URL.createObjectURL(blob);
2314
+ b.recordingState.recording = new Audio(b.recordingState.audioURL);
2315
+ b.recordingState.initListeners();
2316
+ b.recordingState.currentlyRecording = false;
2317
+ b.recordingState.recorder = null;
2318
+ b.recordingState.chunks = [];
2319
+ }
2294
2320
  async function record() {
2295
- //request permission is asynchronous
2296
2321
  let b = pxsim.board();
2297
- if (!b.recordingState.currentlyRecording) {
2298
- b.recordingState.currentlyRecording = true;
2299
- pxsim.runtime.queueDisplayUpdate();
2300
- if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
2301
- try {
2302
- stream = await navigator.mediaDevices.getUserMedia({ video: false, audio: true });
2303
- recorder = new MediaRecorder(stream);
2304
- recorder.start();
2305
- setTimeout(() => {
2306
- recorder.stop();
2307
- pxsim.runtime.queueDisplayUpdate();
2308
- }, 4000);
2309
- recorder.ondataavailable = (e) => {
2310
- chunks.push(e.data);
2311
- };
2312
- recorder.onstop = () => {
2313
- const blob = new Blob(chunks, { type: "audio/ogg; codecs=opus" });
2314
- audioURL = window.URL.createObjectURL(blob);
2315
- recording = new Audio(audioURL);
2316
- b.recordingState.currentlyRecording = false;
2317
- erase();
2318
- };
2319
- }
2320
- catch (error) {
2321
- console.log("An error occurred, could not get microphone access");
2322
- }
2322
+ if (b.recordingState.recorder) {
2323
+ b.recordingState.recorder.stop();
2324
+ clearTimeout(b.recordingState.recordTimeoutID);
2325
+ }
2326
+ if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
2327
+ try {
2328
+ b.recordingState.stream = await navigator.mediaDevices.getUserMedia({ video: false, audio: true });
2329
+ b.recordingState.recorder = new MediaRecorder(b.recordingState.stream);
2330
+ b.recordingState.recorder.start();
2331
+ b.recordingState.currentlyRecording = true;
2332
+ pxsim.runtime.queueDisplayUpdate();
2333
+ b.recordingState.recordTimeoutID = setTimeout(() => {
2334
+ stopRecorder(b);
2335
+ pxsim.runtime.queueDisplayUpdate();
2336
+ }, 5000);
2337
+ b.recordingState.recorder.ondataavailable = (e) => {
2338
+ b.recordingState.chunks.push(e.data);
2339
+ };
2340
+ b.recordingState.recorder.onstop = () => {
2341
+ populateRecording(b);
2342
+ registerSimStop(b);
2343
+ };
2323
2344
  }
2324
- else {
2325
- console.log("getUserMedia not supported on your browser!");
2345
+ catch (error) {
2346
+ console.log("An error occurred, could not get microphone access");
2347
+ if (b.recordingState.recorder) {
2348
+ b.recordingState.recorder.stop();
2349
+ }
2350
+ b.recordingState.currentlyRecording = false;
2326
2351
  }
2327
2352
  }
2353
+ else {
2354
+ console.log("getUserMedia not supported on your browser!");
2355
+ b.recordingState.currentlyRecording = false;
2356
+ }
2328
2357
  }
2329
2358
  record_1.record = record;
2359
+ function stopAudio() {
2360
+ const b = pxsim.board();
2361
+ if (!b)
2362
+ return;
2363
+ if (b.recordingState.currentlyRecording && b.recordingState.recordTimeoutID) {
2364
+ clearTimeout(b.recordingState.recordTimeoutID);
2365
+ stopRecorder(b);
2366
+ }
2367
+ else if (b.recordingState.recording && b.recordingState.audioPlaying) {
2368
+ b.recordingState.handleAudioStopped();
2369
+ b.recordingState.recording.pause();
2370
+ b.recordingState.recording.currentTime = 0;
2371
+ }
2372
+ }
2373
+ function registerSimStop(b) {
2374
+ pxsim.AudioContextManager.onStopAll(() => {
2375
+ if (b.recordingState.recording) {
2376
+ stopAudio();
2377
+ b.recordingState.recording.removeEventListener("play", b.recordingState.handleAudioPlaying);
2378
+ b.recordingState.recording.removeEventListener("ended", b.recordingState.handleAudioStopped);
2379
+ }
2380
+ });
2381
+ }
2330
2382
  function play() {
2331
- if (recording) {
2332
- recording.play();
2333
- }
2383
+ const b = pxsim.board();
2384
+ if (!b)
2385
+ return;
2386
+ stopAudio();
2387
+ b.recordingState.audioPlaying = true;
2388
+ setTimeout(() => {
2389
+ if (b.recordingState.recording) {
2390
+ b.recordingState.recording.play();
2391
+ }
2392
+ }, 10);
2334
2393
  }
2335
2394
  record_1.play = play;
2336
2395
  function stop() {
2396
+ stopAudio();
2337
2397
  }
2338
2398
  record_1.stop = stop;
2339
2399
  function erase() {
2340
- chunks = [];
2400
+ const b = pxsim.board();
2401
+ if (!b)
2402
+ return;
2403
+ b.recordingState.chunks = [];
2404
+ if (b.recordingState.audioPlaying) {
2405
+ b.recordingState.recording.pause();
2406
+ b.recordingState.audioPlaying = false;
2407
+ b.recordingState.recording.currentTime = 0;
2408
+ }
2409
+ window.URL.revokeObjectURL(b.recordingState.audioURL);
2410
+ b.recordingState.recording = null;
2341
2411
  }
2342
2412
  record_1.erase = erase;
2343
2413
  function setMicrophoneGain(gain) {
@@ -2348,23 +2418,26 @@ var pxsim;
2348
2418
  }
2349
2419
  record_1.audioDuration = audioDuration;
2350
2420
  function audioIsPlaying() {
2351
- if (recording) {
2352
- recording.addEventListener("playing", () => {
2353
- audioPlaying = true;
2354
- }, { once: true });
2355
- recording.addEventListener("ended", () => {
2356
- audioPlaying = false;
2357
- }, { once: true });
2358
- }
2359
- return audioPlaying;
2421
+ const b = pxsim.board();
2422
+ if (!b)
2423
+ return false;
2424
+ return b.recordingState.audioPlaying;
2360
2425
  }
2361
2426
  record_1.audioIsPlaying = audioIsPlaying;
2362
2427
  function audioIsRecording() {
2363
- return recorder ? recorder.state == "recording" : false;
2428
+ const b = pxsim.board();
2429
+ if (!b)
2430
+ return false;
2431
+ return b.recordingState.recorder ? b.recordingState.recorder.state === "recording" : false;
2364
2432
  }
2365
2433
  record_1.audioIsRecording = audioIsRecording;
2366
2434
  function audioIsStopped() {
2367
- return recorder ? !audioPlaying && recorder.state == "inactive" : true;
2435
+ const b = pxsim.board();
2436
+ if (!b)
2437
+ return true;
2438
+ const isNotPlaying = !audioIsPlaying();
2439
+ const isNotRecording = !audioIsRecording();
2440
+ return b.recordingState.recording ? isNotPlaying && isNotRecording : false;
2368
2441
  }
2369
2442
  record_1.audioIsStopped = audioIsStopped;
2370
2443
  function setInputSampleRate(sampleRate) {