@alan-ai/alan-sdk-web 1.8.39 → 1.8.41

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/alan_lib.js CHANGED
@@ -493,18 +493,22 @@
493
493
  var isIE = false || !!document.documentMode;
494
494
  var isEdge = !isIE && !!window.StyleMedia;
495
495
  var isChrome = /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor);
496
+ var isMobileIos = navigator.userAgent.match(/safari/i) && navigator.vendor.match(/apple/i) && navigator.maxTouchPoints;
496
497
 
497
498
  if (isEdge || isChrome) {
498
499
  audioContext = new AudioContext({sampleRate: config.sampleRate});
499
500
  } else {
500
501
  audioContext = new AudioContext();
501
502
  }
502
-
503
+
503
504
  audioContext.resume().then(()=> fireEvent(AUDIO_RUNNING));
504
505
 
505
506
  var microphoneStream = null;
506
507
  var microphoneNode = null;
507
508
  var gainNode = audioContext.createGain();
509
+ var audioGainNode = audioContext.createGain();
510
+ audioGainNode.gain.value = 1;
511
+ var audioBufferSource = null;
508
512
  var encoderNode = audioContext.createScriptProcessor(config.bufferLength, 1, 1);
509
513
  encoderNode.onaudioprocess = ({inputBuffer}) => encodeBuffers(inputBuffer);
510
514
  encoderNode.connect(audioContext.destination);
@@ -561,27 +565,87 @@
561
565
  });
562
566
  }
563
567
 
568
+ function onPlayEnded() {
569
+ playState = PLAY_IDLE;
570
+ _handleQueue(true);
571
+ }
572
+
564
573
  function getAudioElement() {
565
574
  if (audioElement) {
566
575
  return audioElement;
567
576
  }
568
577
  audioElement = document.createElement("audio");
569
578
  audioElement.addEventListener("ended", function() {
570
- playState = PLAY_IDLE;
571
- _handleQueue(true);
579
+ onPlayEnded();
572
580
  });
573
581
  document.body.appendChild(audioElement);
574
582
  audioElement.setAttribute("autoplay", "true");
575
583
  return audioElement;
576
584
  }
577
585
 
586
+ function _base64ToArrayBuffer(base64) {
587
+ var binary_string = window.atob(base64);
588
+ var len = binary_string.length;
589
+ var bytes = new Uint8Array(len);
590
+ for (var i = 0; i < len; i++) {
591
+ bytes[i] = binary_string.charCodeAt(i);
592
+ }
593
+ return bytes.buffer;
594
+ }
595
+
596
+ function playAudio(audio) {
597
+ if (isMobileIos) {
598
+ const base64prefix = "data:audio/mpeg;base64,";
599
+ if (audio.startsWith(base64prefix)) {
600
+ audio = audio.substring(base64prefix.length);
601
+ }
602
+ var audioData = _base64ToArrayBuffer(audio);
603
+ audioContext.decodeAudioData(
604
+ audioData,
605
+ (buffer) => {
606
+ audioBufferSource = audioContext.createBufferSource();
607
+ audioBufferSource.addEventListener('ended', e => onPlayEnded());
608
+ audioBufferSource.connect(gainNode);
609
+ audioBufferSource.connect(audioGainNode);
610
+ audioGainNode.connect(audioContext.destination);
611
+ audioBufferSource.loop = false;
612
+ audioBufferSource.buffer = buffer;
613
+ audioBufferSource.start(0);
614
+ },
615
+ (err) => console.error(`Error with decoding audio data: ${err.err}`)
616
+ );
617
+ } else {
618
+ getAudioElement().setAttribute("src", audio);
619
+ }
620
+ }
621
+
622
+ function stopPlaying() {
623
+ if (isMobileIos) {
624
+ if (audioBufferSource) {
625
+ audioBufferSource.stop();
626
+ }
627
+ } else {
628
+ if (audioElement) {
629
+ audioElement.pause();
630
+ audioElement.currentTime = 0;
631
+ audioElement.src = "";
632
+ }
633
+ }
634
+ }
635
+
636
+ function onStopPlaying() {
637
+ if (!isMobileIos) {
638
+ getAudioElement().setAttribute("src", "");
639
+ }
640
+ onPlayStop();
641
+ }
642
+
578
643
  function _handleQueue(nowPlaying) {
579
644
  if (audioContext.state === 'suspended') {
580
645
  return;
581
646
  }
582
647
  if (nowPlaying && !audioQueue.length) {
583
- getAudioElement().setAttribute("src", "");
584
- onPlayStop();
648
+ onStopPlaying();
585
649
  }
586
650
  if (!audioQueue.length || playState === PLAY_ACTIVE) {
587
651
  return;
@@ -598,7 +662,7 @@
598
662
  if (playState === PLAY_IDLE) {
599
663
  playState = PLAY_ACTIVE;
600
664
  fireEvent('playStart');
601
- getAudioElement().setAttribute("src", o.audio);
665
+ playAudio(o.audio);
602
666
  }
603
667
  } else {
604
668
  console.error('invalid queue item');
@@ -724,11 +788,16 @@
724
788
  getAudioElement().setAttribute("src", "");
725
789
  playState = PLAY_IDLE;
726
790
  openMicrophone()
727
- .then(()=> {
791
+ .then(()=> {
728
792
  micState = MIC_ACTIVE;
729
793
  fireEvent('micStart');
730
794
  })
731
- .then(()=> { setMicAllowed(true); audioContext.resume();})
795
+ .then(()=> {
796
+ setMicAllowed(true);
797
+ if (!isMobileIos) {
798
+ audioContext.resume();
799
+ }
800
+ })
732
801
  .catch(err => { fireEvent('micFail', err); });
733
802
  if (onStarted) {
734
803
  onStarted();
@@ -748,11 +817,7 @@
748
817
  fireEvent('micStop');
749
818
  playState = PLAY_STOPPED;
750
819
  audioQueue = [];
751
- if (audioElement) {
752
- audioElement.pause();
753
- audioElement.currentTime = 0;
754
- audioElement.src = "";
755
- }
820
+ stopPlaying();
756
821
  };
757
822
 
758
823
  ns.skipExternalSounds = function(skip) {
@@ -781,7 +846,7 @@
781
846
 
782
847
  /// <reference types="../global" />
783
848
  (function (ns) {
784
- var alanButtonVersion = '1.8.39';
849
+ var alanButtonVersion = '1.8.41';
785
850
  if (window.alanBtn) {
786
851
  console.warn('Alan: the Alan Button source code has already added (v.' + alanButtonVersion + ')');
787
852
  }
@@ -968,6 +1033,7 @@
968
1033
  window.tutorProject.off('scripts', onScriptsCb);
969
1034
  window.tutorProject.off('text', onTextCbInMicBtn);
970
1035
  window.tutorProject.off('parsed', onParsedCbInMicBtn);
1036
+ alanAudio.off('command', onCommandCbInMicBtn);
971
1037
  rootEl.innerHTML = '';
972
1038
  btnInstance = null;
973
1039
  if (!isTutorMode()) {
@@ -1890,6 +1956,7 @@
1890
1956
  window.tutorProject.on('scripts', onScriptsCb);
1891
1957
  window.tutorProject.on('text', onTextCbInMicBtn);
1892
1958
  window.tutorProject.on('parsed', onParsedCbInMicBtn);
1959
+ alanAudio.on('command', onCommandCbInMicBtn);
1893
1960
  //window.tutorProject.on('popup', onPopup);
1894
1961
  // console.info('BTN: tutorProject', options.key);
1895
1962
  }
@@ -2021,7 +2088,6 @@
2021
2088
  alanAudio.on('micFail', onMicFail);
2022
2089
  alanAudio.on('playStart', onPlayStart);
2023
2090
  alanAudio.on('playStop', onPlayStop);
2024
- alanAudio.on('command', onCommandCbInMicBtn);
2025
2091
  alanAudio.start(resolve);
2026
2092
  if (options.onMicStarted) {
2027
2093
  options.onMicStarted();
@@ -2581,9 +2647,12 @@
2581
2647
  turnOffVoiceFn();
2582
2648
  }
2583
2649
  function onCommandCbInMicBtn(e) {
2650
+ var _a, _b;
2584
2651
  // console.info('BTN: onCommandCbInMicBtn', e, new Date());
2585
- if (options.onCommand) {
2586
- options.onCommand(e.data);
2652
+ if (isAlanActive || (!isAlanActive && ((_b = (_a = e.ctx) === null || _a === void 0 ? void 0 : _a.opts) === null || _b === void 0 ? void 0 : _b.force) === true)) {
2653
+ if (options.onCommand) {
2654
+ options.onCommand(e.data);
2655
+ }
2587
2656
  }
2588
2657
  if (isAlanActive) {
2589
2658
  switchState(LISTENING);