@stormstreaming/stormstreamer 0.9.0-beta.3 → 0.9.0-beta.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/dist/amd/index.js CHANGED
@@ -4,8 +4,8 @@
4
4
  * contact@stormstreaming.com
5
5
  * https://stormstreaming.com
6
6
  *
7
- * Version: 0.9.0-beta.3
8
- * Version: 12/5/2024, 2:36:50 PM
7
+ * Version: 0.9.0-beta.4
8
+ * Version: 12/7/2024, 6:37:55 PM
9
9
  *
10
10
  * LEGAL NOTICE:
11
11
  * This software is subject to the terms and conditions defined in
@@ -1180,6 +1180,12 @@
1180
1180
  localStorage.setItem(this.prefix + name, value);
1181
1181
  }
1182
1182
  }
1183
+ removeField(name) {
1184
+ if (this.isEnabled) {
1185
+ if (this.LOG_ACTIVITY) this.logger.info(this, "Removing data: " + name);
1186
+ localStorage.removeItem(this.prefix + name);
1187
+ }
1188
+ }
1183
1189
  getField(name) {
1184
1190
  if (this.isEnabled == true) {
1185
1191
  const value = localStorage.getItem(this.prefix + name);
@@ -1777,7 +1783,6 @@
1777
1783
  if (typeof container === "string") {
1778
1784
  this._logger.info(this, "Attaching container to ID: " + container);
1779
1785
  tempParentElement = document.getElementById(container);
1780
- console.log(">>", document.getElementById(container));
1781
1786
  } else if (container instanceof HTMLElement) {
1782
1787
  this._logger.info(this, "Attaching container to HTMLElement: " + container);
1783
1788
  tempParentElement = container;
@@ -2514,21 +2519,21 @@
2514
2519
  let sum = 0.0;
2515
2520
  let clipcount = 0;
2516
2521
  for (let i = 0; i < dataArray.length; ++i) {
2517
- const amplitude = dataArray[i];
2522
+ const amplitude = dataArray[i] * 3.16;
2518
2523
  sum += amplitude * amplitude;
2519
2524
  if (Math.abs(amplitude) > 0.99) {
2520
2525
  clipcount += 1;
2521
2526
  }
2522
2527
  }
2523
- this._instant = Math.sqrt(sum / dataArray.length);
2524
- this._slow = 0.05 * this._instant + 0.95 * this._slow;
2528
+ this._instant = Math.min(1, Math.sqrt(sum / dataArray.length));
2529
+ this._slow = Math.min(1, 0.05 * this._instant + 0.95 * this._slow);
2525
2530
  this._clip = clipcount / dataArray.length;
2526
2531
  if (now - this._lastEventTime >= this.THROTTLE_INTERVAL) {
2527
2532
  this._lastEventTime = now;
2528
2533
  this._main.dispatchEvent("soundMeter", {
2529
2534
  ref: this._main,
2530
- high: this._instant,
2531
- low: this._slow
2535
+ high: Number(this._instant.toFixed(4)),
2536
+ low: Number(this._slow.toFixed(4))
2532
2537
  });
2533
2538
  }
2534
2539
  requestAnimationFrame(analyze);
@@ -2545,6 +2550,7 @@
2545
2550
  };
2546
2551
  this._isMicrophoneMuted = false;
2547
2552
  this._pendingMicrophoneState = null;
2553
+ this._permissionChecked = false;
2548
2554
  this._constraints = {
2549
2555
  video: {
2550
2556
  width: {
@@ -2641,10 +2647,9 @@
2641
2647
  };
2642
2648
  this._main = main;
2643
2649
  this._logger = main.getLogger();
2644
- this._logger.info(this, "Creating new PlaybackController");
2645
2650
  this._mungeSDP = new MungeSDP();
2646
2651
  this._soundMeter = new SoundMeter(this._main);
2647
- this.initialize();
2652
+ this.initializeDevices();
2648
2653
  }
2649
2654
  initialize() {
2650
2655
  var _a, _b;
@@ -2653,16 +2658,64 @@
2653
2658
  document.addEventListener("visibilitychange", this.visibilityChange);
2654
2659
  window.addEventListener("blur", this.onWindowBlur);
2655
2660
  window.addEventListener("focus", this.onWindowFocus);
2661
+ if (this._selectedCamera || this._selectedMicrophone) {
2662
+ this.startCamera().then(() => {
2663
+ var _a;
2664
+ if (((_a = this._main.getConfigManager()) === null || _a === void 0 ? void 0 : _a.getStreamData().streamKey) != null) {
2665
+ this.initializeWebRTC();
2666
+ }
2667
+ });
2668
+ }
2656
2669
  if ((_a = this._main.getConfigManager()) === null || _a === void 0 ? void 0 : _a.getSettingsData().autoConnect) {
2657
2670
  this._logger.info(this, "Initializing NetworkController (autoConnect is true)");
2658
2671
  (_b = this._main.getNetworkController()) === null || _b === void 0 ? void 0 : _b.initialize();
2659
2672
  } else {
2660
2673
  this._logger.warning(this, "Warning - autoConnect is set to false, switching to standby mode!");
2661
2674
  }
2662
- this.startCamera().then(() => {
2663
- var _a;
2664
- if (((_a = this._main.getConfigManager()) === null || _a === void 0 ? void 0 : _a.getStreamData().streamKey) != null) {
2665
- this.initializeWebRTC();
2675
+ this.setupPermissionListeners();
2676
+ }
2677
+ initializeDevices() {
2678
+ return __awaiter(this, void 0, void 0, function* () {
2679
+ try {
2680
+ yield this.grabDevices();
2681
+ this.setupPermissionListeners();
2682
+ this.initialize();
2683
+ } catch (error) {
2684
+ this._logger.error(this, "Error initializing devices: " + JSON.stringify(error));
2685
+ this.initialize();
2686
+ }
2687
+ });
2688
+ }
2689
+ setupPermissionListeners() {
2690
+ const cameraQuery = {
2691
+ name: 'camera'
2692
+ };
2693
+ const microphoneQuery = {
2694
+ name: 'microphone'
2695
+ };
2696
+ navigator.permissions.query(cameraQuery).then(permissionStatus => {
2697
+ permissionStatus.onchange = () => {
2698
+ this._permissionChecked = false;
2699
+ this.handlePermissionChange('camera', permissionStatus.state);
2700
+ };
2701
+ });
2702
+ navigator.permissions.query(microphoneQuery).then(permissionStatus => {
2703
+ permissionStatus.onchange = () => {
2704
+ this._permissionChecked = false;
2705
+ this.handlePermissionChange('microphone', permissionStatus.state);
2706
+ };
2707
+ });
2708
+ }
2709
+ handlePermissionChange(device, state) {
2710
+ return __awaiter(this, void 0, void 0, function* () {
2711
+ if (state === 'denied') {
2712
+ if (this._publishState == exports.PublishState.PUBLISHED) {
2713
+ this.closeStream();
2714
+ }
2715
+ }
2716
+ yield this.grabDevices();
2717
+ if (state === 'granted') {
2718
+ yield this.startCamera();
2666
2719
  }
2667
2720
  });
2668
2721
  }
@@ -2726,105 +2779,94 @@
2726
2779
  this.closeStream();
2727
2780
  }
2728
2781
  onUserMediaError(error) {
2729
- console.log('%c⏵ 🎥 onUserMediaError: ' + JSON.stringify(error), 'background: green; color: white;');
2730
- const errorName = error.name || '';
2731
- const errorMessage = error.message || '';
2732
- if (error.deviceType) {
2733
- if (error.deviceType === 'video') {
2734
- this._main.dispatchEvent("cameraAccessDenied", {
2735
- ref: this._main
2736
- });
2737
- } else if (error.deviceType === 'audio') {
2738
- this._main.dispatchEvent("microphoneAccessDenied", {
2739
- ref: this._main
2740
- });
2782
+ return __awaiter(this, void 0, void 0, function* () {
2783
+ yield this.grabDevices();
2784
+ if (error.name === "OverconstrainedError") {
2785
+ this._logger.warning(this, "Device constraints not satisfied");
2741
2786
  }
2742
- this.grabDevices();
2743
- return;
2744
- }
2745
- if (errorName === 'NotAllowedError' || errorMessage.includes('Permission denied') || errorMessage.includes('not allowed')) {
2746
- this.checkIndividualDeviceAccess().then(results => {
2747
- if (!results.camera && !results.microphone) {
2748
- this._main.dispatchEvent("cameraAccessDenied", {
2749
- ref: this._main
2750
- });
2751
- this._main.dispatchEvent("microphoneAccessDenied", {
2752
- ref: this._main
2753
- });
2754
- } else {
2755
- if (!results.camera) {
2756
- this._main.dispatchEvent("cameraAccessDenied", {
2757
- ref: this._main
2758
- });
2759
- }
2760
- if (!results.microphone) {
2761
- this._main.dispatchEvent("microphoneAccessDenied", {
2762
- ref: this._main
2763
- });
2764
- }
2765
- }
2766
- this.grabDevices();
2767
- });
2768
- return;
2769
- }
2770
- if (errorName === 'NotFoundError' || errorMessage.includes('Requested device not found')) {
2771
- this.checkDeviceAvailability().then(results => {
2772
- if (!results.camera) {
2773
- this._main.dispatchEvent("noCameraFound", {
2774
- ref: this._main
2775
- });
2776
- }
2777
- if (!results.microphone) {
2778
- this._main.dispatchEvent("noMicrophoneFound", {
2779
- ref: this._main
2780
- });
2781
- }
2782
- this.grabDevices();
2783
- });
2784
- return;
2785
- }
2786
- this._logger.warning(this, "WebRTCStreamer :: Unsupported onUserMediaError: " + errorMessage);
2787
- this._main.dispatchEvent("inputDeviceError", {
2788
- ref: this._main
2789
2787
  });
2790
- this.grabDevices();
2791
2788
  }
2792
2789
  checkIndividualDeviceAccess() {
2793
2790
  return __awaiter(this, void 0, void 0, function* () {
2794
2791
  const results = {
2795
- camera: false,
2796
- microphone: false
2792
+ camera: {
2793
+ allowed: false,
2794
+ available: false
2795
+ },
2796
+ microphone: {
2797
+ allowed: false,
2798
+ available: false
2799
+ }
2797
2800
  };
2801
+ const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
2802
+ const isEdge = /edg/i.test(navigator.userAgent);
2803
+ const isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
2798
2804
  try {
2799
- const videoStream = yield navigator.mediaDevices.getUserMedia({
2800
- video: true
2801
- });
2802
- results.camera = true;
2803
- videoStream.getTracks().forEach(track => track.stop());
2804
- } catch (e) {
2805
- results.camera = false;
2805
+ const devices = yield navigator.mediaDevices.enumerateDevices();
2806
+ results.camera.available = devices.some(device => device.kind === 'videoinput');
2807
+ results.microphone.available = devices.some(device => device.kind === 'audioinput');
2808
+ } catch (error) {
2809
+ console.error("Error checking device availability:", error);
2806
2810
  }
2807
- try {
2808
- const audioStream = yield navigator.mediaDevices.getUserMedia({
2809
- audio: true
2810
- });
2811
- results.microphone = true;
2812
- audioStream.getTracks().forEach(track => track.stop());
2813
- } catch (e) {
2814
- results.microphone = false;
2811
+ if (isFirefox) {
2812
+ console.log("Firefox detected, using direct getUserMedia check...");
2813
+ if (results.camera.available) {
2814
+ try {
2815
+ const stream = yield navigator.mediaDevices.getUserMedia({
2816
+ video: true
2817
+ });
2818
+ results.camera.allowed = true;
2819
+ stream.getTracks().forEach(track => track.stop());
2820
+ } catch (e) {
2821
+ console.log("Camera permission check failed:", e);
2822
+ results.camera.allowed = false;
2823
+ }
2824
+ }
2825
+ if (results.microphone.available) {
2826
+ try {
2827
+ const stream = yield navigator.mediaDevices.getUserMedia({
2828
+ audio: true
2829
+ });
2830
+ results.microphone.allowed = true;
2831
+ stream.getTracks().forEach(track => track.stop());
2832
+ } catch (e) {
2833
+ console.log("Microphone permission check failed:", e);
2834
+ results.microphone.allowed = false;
2835
+ }
2836
+ }
2837
+ } else {
2838
+ try {
2839
+ const [cameraPermission, microphonePermission] = yield Promise.all([navigator.permissions.query({
2840
+ name: 'camera'
2841
+ }), navigator.permissions.query({
2842
+ name: 'microphone'
2843
+ })]);
2844
+ results.camera.allowed = cameraPermission.state === "granted";
2845
+ results.microphone.allowed = microphonePermission.state === "granted";
2846
+ if ((isSafari || isEdge) && (!results.camera.allowed || !results.microphone.allowed)) {
2847
+ try {
2848
+ const stream = yield navigator.mediaDevices.getUserMedia({
2849
+ video: results.camera.available && !results.camera.allowed,
2850
+ audio: results.microphone.available && !results.microphone.allowed
2851
+ });
2852
+ if (stream.getVideoTracks().length > 0) {
2853
+ results.camera.allowed = true;
2854
+ }
2855
+ if (stream.getAudioTracks().length > 0) {
2856
+ results.microphone.allowed = true;
2857
+ }
2858
+ stream.getTracks().forEach(track => track.stop());
2859
+ } catch (error) {
2860
+ console.log("Additional permission check failed:", error);
2861
+ }
2862
+ }
2863
+ } catch (error) {
2864
+ console.error("Error checking permissions:", error);
2865
+ }
2815
2866
  }
2816
2867
  return results;
2817
2868
  });
2818
2869
  }
2819
- checkDeviceAvailability() {
2820
- return __awaiter(this, void 0, void 0, function* () {
2821
- const devices = yield navigator.mediaDevices.enumerateDevices();
2822
- return {
2823
- camera: devices.some(device => device.kind === 'videoinput'),
2824
- microphone: devices.some(device => device.kind === 'audioinput')
2825
- };
2826
- });
2827
- }
2828
2870
  onSocketMessage(data) {
2829
2871
  let msgJSON = JSON.parse(data);
2830
2872
  let msgStatus = Number(msgJSON["status"]);
@@ -2882,60 +2924,61 @@
2882
2924
  grabDevices() {
2883
2925
  return __awaiter(this, void 0, void 0, function* () {
2884
2926
  try {
2885
- try {
2886
- yield navigator.mediaDevices.getUserMedia({
2887
- audio: true,
2888
- video: true
2889
- });
2890
- } catch (e) {}
2891
- const devices = yield navigator.mediaDevices.enumerateDevices();
2927
+ const deviceAccess = yield this.checkIndividualDeviceAccess();
2892
2928
  this._cameraList = new InputDeviceList();
2893
2929
  this._microphoneList = new InputDeviceList();
2894
- for (let device of devices) {
2895
- try {
2896
- if (device.deviceId && device.label) {
2897
- if (device.kind === 'videoinput') {
2898
- let inputDevice = new InputDevice(device, this._cameraList.getSize());
2899
- this._cameraList.push(inputDevice);
2900
- } else if (device.kind === 'audioinput') {
2901
- let inputDevice = new InputDevice(device, this._microphoneList.getSize());
2902
- this._microphoneList.push(inputDevice);
2903
- }
2904
- }
2905
- } catch (error) {
2906
- this._logger.error(this, "WebRTCStreamer :: Input Device Error: " + error);
2930
+ if (!this._permissionChecked) {
2931
+ if (!deviceAccess.camera.allowed) {
2932
+ this._main.dispatchEvent("cameraAccessDenied", {
2933
+ ref: this._main
2934
+ });
2935
+ } else if (!deviceAccess.camera.available) {
2936
+ this._main.dispatchEvent("noCameraFound", {
2937
+ ref: this._main
2938
+ });
2939
+ }
2940
+ if (!deviceAccess.microphone.allowed) {
2941
+ this._main.dispatchEvent("microphoneAccessDenied", {
2942
+ ref: this._main
2943
+ });
2944
+ } else if (!deviceAccess.microphone.available) {
2945
+ this._main.dispatchEvent("noMicrophoneFound", {
2946
+ ref: this._main
2947
+ });
2907
2948
  }
2908
2949
  }
2909
- this._logger.info(this, "Camera list:");
2910
- for (let i = 0; i < this._cameraList.getSize(); i++) {
2911
- this._logger.info(this, "=> [" + i + "] InputDevice: " + this._cameraList.get(i).getLabel());
2912
- }
2913
- this._logger.info(this, "Microphone list:");
2914
- for (let k = 0; k < this._microphoneList.getSize(); k++) {
2915
- this._logger.info(this, "=> [" + k + "] InputDevice: " + this._microphoneList.get(k).getLabel());
2916
- }
2917
- if (this._cameraList.getSize() == 0) {
2918
- this._main.dispatchEvent("noCameraFound", {
2919
- ref: this._main
2920
- });
2921
- } else {
2922
- this._selectedCamera = this.pickCamera();
2950
+ const devices = yield navigator.mediaDevices.enumerateDevices();
2951
+ for (const device of devices) {
2952
+ if (device.deviceId && device.label) {
2953
+ if (device.kind === 'videoinput' && deviceAccess.camera.allowed) {
2954
+ const inputDevice = new InputDevice(device, this._cameraList.getSize());
2955
+ this._cameraList.push(inputDevice);
2956
+ } else if (device.kind === 'audioinput' && deviceAccess.microphone.allowed) {
2957
+ const inputDevice = new InputDevice(device, this._microphoneList.getSize());
2958
+ this._microphoneList.push(inputDevice);
2959
+ }
2960
+ }
2923
2961
  }
2924
- if (this._microphoneList.getSize() == 0) {
2925
- this._main.dispatchEvent("noMicrophoneFound", {
2926
- ref: this._main
2927
- });
2928
- } else {
2929
- this._selectedMicrophone = this.pickMicrophone();
2962
+ try {
2963
+ if (deviceAccess.camera.allowed) {
2964
+ this._selectedCamera = this.pickCamera();
2965
+ }
2966
+ if (deviceAccess.microphone.allowed) {
2967
+ this._selectedMicrophone = this.pickMicrophone();
2968
+ }
2969
+ } catch (error) {
2970
+ this._logger.error(this, "Errror on grab devices: " + JSON.stringify(error));
2930
2971
  }
2931
2972
  this._main.dispatchEvent("deviceListUpdate", {
2932
2973
  ref: this._main,
2933
2974
  cameraList: this._cameraList.getArray(),
2934
2975
  microphoneList: this._microphoneList.getArray()
2935
2976
  });
2977
+ this._permissionChecked = true;
2936
2978
  } catch (error) {
2937
- if (!this._cameraList) this._cameraList = new InputDeviceList();
2938
- if (!this._microphoneList) this._microphoneList = new InputDeviceList();
2979
+ console.error("Error in grabDevices:", error);
2980
+ this._cameraList = new InputDeviceList();
2981
+ this._microphoneList = new InputDeviceList();
2939
2982
  this._main.dispatchEvent("deviceListUpdate", {
2940
2983
  ref: this._main,
2941
2984
  cameraList: this._cameraList.getArray(),
@@ -2948,109 +2991,117 @@
2948
2991
  });
2949
2992
  }
2950
2993
  selectCamera(cameraID) {
2951
- var _a;
2994
+ var _a, _b;
2995
+ const streamKey = (_a = this._main.getConfigManager()) === null || _a === void 0 ? void 0 : _a.getStreamData().streamKey;
2996
+ const wasPublished = this._publishState === exports.PublishState.PUBLISHED;
2952
2997
  for (let i = 0; i < this._cameraList.getSize(); i++) {
2953
2998
  if (this._cameraList.get(i).getID() == cameraID) {
2954
2999
  this._selectedCamera = this._cameraList.get(i);
2955
- (_a = this._main.getStorageManager()) === null || _a === void 0 ? void 0 : _a.saveField("cameraID", this._selectedCamera.getID());
3000
+ console.log("kamera znaleziona i zapisana " + this._cameraList.get(i).getLabel() + " " + this._cameraList.get(i).getID());
3001
+ (_b = this._main.getStorageManager()) === null || _b === void 0 ? void 0 : _b.saveField("cameraID", this._selectedCamera.getID());
2956
3002
  break;
2957
3003
  }
2958
3004
  }
2959
- const wasPublishing = this._publishState === exports.PublishState.PUBLISHED;
2960
3005
  this.stopCameraStream();
2961
3006
  this._constraints.video.deviceId = this._selectedCamera.getID();
2962
3007
  this.startCamera().then(() => {
2963
- var _a;
2964
- if (wasPublishing && ((_a = this._main.getConfigManager()) === null || _a === void 0 ? void 0 : _a.getStreamData().streamKey)) {
2965
- this.updateWebRTCStream();
3008
+ if (wasPublished && streamKey) {
3009
+ this.publish(streamKey);
2966
3010
  }
2967
3011
  });
2968
3012
  }
2969
3013
  selectMicrophone(micID) {
2970
- var _a;
2971
- for (let i = 0; i < this._microphoneList.getSize(); i++) {
2972
- if (this._microphoneList.get(i).getID() == micID) {
2973
- this._selectedMicrophone = this._microphoneList.get(i);
2974
- (_a = this._main.getStorageManager()) === null || _a === void 0 ? void 0 : _a.saveField("microphoneID", this._selectedMicrophone.getID());
2975
- break;
3014
+ var _a, _b, _c, _d, _e, _f;
3015
+ return __awaiter(this, void 0, void 0, function* () {
3016
+ console.log("🎤 Selecting microphone:", micID);
3017
+ const streamKey = (_a = this._main.getConfigManager()) === null || _a === void 0 ? void 0 : _a.getStreamData().streamKey;
3018
+ const wasPublished = this._publishState === exports.PublishState.PUBLISHED;
3019
+ for (let i = 0; i < this._microphoneList.getSize(); i++) {
3020
+ if (this._microphoneList.get(i).getID() == micID) {
3021
+ this._selectedMicrophone = this._microphoneList.get(i);
3022
+ (_b = this._main.getStorageManager()) === null || _b === void 0 ? void 0 : _b.saveField("microphoneID", this._selectedMicrophone.getID());
3023
+ break;
3024
+ }
2976
3025
  }
2977
- }
2978
- const wasPublishing = this._publishState === exports.PublishState.PUBLISHED;
2979
- this.stopCameraStream();
2980
- this._constraints.audio = {
2981
- deviceId: this._selectedMicrophone.getID()
2982
- };
2983
- this.startCamera().then(() => {
2984
- var _a;
2985
- if (wasPublishing && ((_a = this._main.getConfigManager()) === null || _a === void 0 ? void 0 : _a.getStreamData().streamKey)) {
2986
- this.updateWebRTCStream();
3026
+ this._soundMeter.detach();
3027
+ (_c = this._stream) === null || _c === void 0 ? void 0 : _c.getAudioTracks().forEach(track => track.stop());
3028
+ try {
3029
+ const audioStream = yield navigator.mediaDevices.getUserMedia({
3030
+ audio: {
3031
+ deviceId: {
3032
+ exact: (_d = this._selectedMicrophone) === null || _d === void 0 ? void 0 : _d.getID()
3033
+ }
3034
+ }
3035
+ });
3036
+ const oldAudioTracks = ((_e = this._stream) === null || _e === void 0 ? void 0 : _e.getAudioTracks()) || [];
3037
+ oldAudioTracks.forEach(track => {
3038
+ var _a;
3039
+ (_a = this._stream) === null || _a === void 0 ? void 0 : _a.removeTrack(track);
3040
+ track.stop();
3041
+ });
3042
+ const newAudioTrack = audioStream.getAudioTracks()[0];
3043
+ (_f = this._stream) === null || _f === void 0 ? void 0 : _f.addTrack(newAudioTrack);
3044
+ this._soundMeter.detach();
3045
+ yield new Promise(resolve => setTimeout(resolve, 100));
3046
+ if (this._stream) {
3047
+ this._soundMeter.attach(this._stream);
3048
+ }
3049
+ if (wasPublished && streamKey) {
3050
+ this.publish(streamKey);
3051
+ }
3052
+ } catch (error) {
3053
+ console.error("Error changing microphone:", error);
2987
3054
  }
2988
3055
  });
2989
3056
  }
2990
3057
  startCamera() {
2991
3058
  return __awaiter(this, void 0, void 0, function* () {
3059
+ if (this._stream) {
3060
+ console.log("Stopping existing stream before starting new one");
3061
+ this._stream.getTracks().forEach(track => {
3062
+ track.stop();
3063
+ });
3064
+ this._stream = null;
3065
+ }
2992
3066
  try {
2993
- const devices = yield navigator.mediaDevices.enumerateDevices();
2994
- const hasVideo = devices.some(device => device.kind === 'videoinput');
2995
- const hasAudio = devices.some(device => device.kind === 'audioinput');
2996
- let tracks = [];
2997
- let hadError = false;
2998
- if (hasVideo) {
2999
- try {
3000
- const videoStream = yield navigator.mediaDevices.getUserMedia({
3001
- video: this._constraints.video
3002
- });
3003
- tracks.push(...videoStream.getTracks());
3004
- } catch (error) {
3005
- hadError = true;
3067
+ const constraints = {
3068
+ video: this._selectedCamera ? Object.assign(Object.assign({}, this._constraints.video), {
3069
+ deviceId: {
3070
+ exact: this._selectedCamera.getID()
3071
+ }
3072
+ }) : false,
3073
+ audio: this._selectedMicrophone ? {
3074
+ deviceId: {
3075
+ exact: this._selectedMicrophone.getID()
3076
+ }
3077
+ } : false
3078
+ };
3079
+ try {
3080
+ const stream = yield navigator.mediaDevices.getUserMedia(constraints);
3081
+ this._stream = stream;
3082
+ this.onCameraStreamSuccess(this._stream);
3083
+ } catch (error) {
3084
+ if (constraints.video) {
3006
3085
  this.onUserMediaError({
3007
- name: error instanceof Error ? error.name : 'UnknownError',
3008
- message: error instanceof Error ? error.message : 'Unknown error',
3086
+ name: error.name || 'Error',
3087
+ message: error.message || 'Unknown error',
3009
3088
  deviceType: 'video'
3010
3089
  });
3011
3090
  }
3012
- }
3013
- if (hasAudio) {
3014
- try {
3015
- const audioStream = yield navigator.mediaDevices.getUserMedia({
3016
- audio: this._constraints.audio
3017
- });
3018
- tracks.push(...audioStream.getTracks());
3019
- } catch (error) {
3020
- hadError = true;
3091
+ if (constraints.audio) {
3021
3092
  this.onUserMediaError({
3022
- name: error instanceof Error ? error.name : 'UnknownError',
3023
- message: error instanceof Error ? error.message : 'Unknown error',
3093
+ name: error.name || 'Error',
3094
+ message: error.message || 'Unknown error',
3024
3095
  deviceType: 'audio'
3025
3096
  });
3026
3097
  }
3027
3098
  }
3028
- if (tracks.length > 0) {
3029
- this._stream = new MediaStream(tracks);
3030
- this.onCameraStreamSuccess(this._stream);
3031
- } else if (hadError) {
3032
- yield this.grabDevices();
3033
- }
3034
3099
  } catch (error) {
3035
- if (error instanceof Error && !('deviceType' in error)) {
3036
- this.onUserMediaError({
3037
- name: error.name,
3038
- message: error.message
3039
- });
3040
- }
3100
+ console.error("Error in startCamera:", error);
3041
3101
  yield this.grabDevices();
3042
3102
  }
3043
3103
  });
3044
3104
  }
3045
- stopCameraStream() {
3046
- if (this._stream) {
3047
- this._stream.getTracks().forEach(track => track.stop());
3048
- const videoElement = this._main.getStageController().getScreenElement().getVideoElement();
3049
- videoElement.srcObject = null;
3050
- this._soundMeter.detach();
3051
- this._stream = null;
3052
- }
3053
- }
3054
3105
  updateWebRTCStream() {
3055
3106
  if (!this._peerConnection || !this._stream) {
3056
3107
  return;
@@ -3077,22 +3128,32 @@
3077
3128
  this._cameraList.get(i).setSelected(false);
3078
3129
  }
3079
3130
  let savedCameraID = (_b = (_a = this._main.getStorageManager()) === null || _a === void 0 ? void 0 : _a.getField("cameraID")) !== null && _b !== void 0 ? _b : null;
3080
- if (this._selectedCamera == null || savedCameraID == null) {
3081
- if (this._cameraList.getSize() > 0) {
3082
- this._selectedCamera = this._cameraList.get(0);
3083
- this._selectedCamera.setSelected(true);
3084
- }
3085
- } else {
3086
- for (let i = 0; i < this._cameraList.getSize(); i++) {
3087
- if (this._cameraList.get(i).getID() == savedCameraID) {
3088
- this._selectedCamera = this._cameraList.get(i);
3089
- this._selectedCamera.setSelected(true);
3090
- break;
3131
+ if (this._cameraList.getSize() > 0) {
3132
+ if (savedCameraID) {
3133
+ let found = false;
3134
+ for (let i = 0; i < this._cameraList.getSize(); i++) {
3135
+ if (this._cameraList.get(i).getID() === savedCameraID) {
3136
+ this._selectedCamera = this._cameraList.get(i);
3137
+ this._selectedCamera.setSelected(true);
3138
+ found = true;
3139
+ this._constraints.video.deviceId = this._selectedCamera.getID();
3140
+ break;
3141
+ }
3142
+ }
3143
+ if (!found) {
3144
+ this._main.dispatchEvent("savedCameraNotFound", {
3145
+ ref: this._main
3146
+ });
3147
+ throw new Error("Specific camera was not found!");
3091
3148
  }
3092
3149
  }
3093
- if (!this._selectedCamera && this._cameraList.getSize() > 0) {
3150
+ if (!this._selectedCamera) {
3151
+ this._main.dispatchEvent("savedCameraNotFound", {
3152
+ ref: this._main
3153
+ });
3094
3154
  this._selectedCamera = this._cameraList.get(0);
3095
3155
  this._selectedCamera.setSelected(true);
3156
+ this._constraints.video.deviceId = this._selectedCamera.getID();
3096
3157
  }
3097
3158
  }
3098
3159
  this._main.dispatchEvent("deviceListUpdate", {
@@ -3108,31 +3169,43 @@
3108
3169
  this._microphoneList.get(i).setSelected(false);
3109
3170
  }
3110
3171
  let savedMicID = (_b = (_a = this._main.getStorageManager()) === null || _a === void 0 ? void 0 : _a.getField("microphoneID")) !== null && _b !== void 0 ? _b : null;
3111
- if (this._selectedMicrophone == null || savedMicID == null) {
3112
- if (this._microphoneList.getSize() > 0) {
3113
- this._selectedMicrophone = this._microphoneList.get(0);
3114
- this._selectedMicrophone.setSelected(true);
3115
- }
3116
- } else {
3117
- for (let i = 0; i < this._microphoneList.getSize(); i++) {
3118
- if (this._microphoneList.get(i).getID() == savedMicID) {
3119
- this._selectedMicrophone = this._microphoneList.get(i);
3120
- this._selectedMicrophone.setSelected(true);
3121
- break;
3172
+ if (this._microphoneList.getSize() > 0) {
3173
+ if (savedMicID) {
3174
+ let found = false;
3175
+ for (let i = 0; i < this._microphoneList.getSize(); i++) {
3176
+ if (this._microphoneList.get(i).getID() === savedMicID) {
3177
+ this._selectedMicrophone = this._microphoneList.get(i);
3178
+ found = true;
3179
+ break;
3180
+ }
3181
+ }
3182
+ if (!found) {
3183
+ this._main.dispatchEvent("savedMicrophoneNotFound", {
3184
+ ref: this._main
3185
+ });
3186
+ throw new Error("Specific microphone was not found!");
3122
3187
  }
3123
3188
  }
3124
- if (!this._selectedMicrophone && this._microphoneList.getSize() > 0) {
3189
+ if (!this._selectedMicrophone) {
3125
3190
  this._selectedMicrophone = this._microphoneList.get(0);
3126
- this._selectedMicrophone.setSelected(true);
3127
3191
  }
3192
+ this._selectedMicrophone.setSelected(true);
3193
+ this._constraints.audio = {
3194
+ deviceId: this._selectedMicrophone.getID()
3195
+ };
3128
3196
  }
3129
- this._main.dispatchEvent("deviceListUpdate", {
3130
- ref: this._main,
3131
- cameraList: this._cameraList.getArray(),
3132
- microphoneList: this._microphoneList.getArray()
3133
- });
3134
3197
  return this._selectedMicrophone;
3135
3198
  }
3199
+ clearSavedDevices() {
3200
+ var _a, _b;
3201
+ (_a = this._main.getStorageManager()) === null || _a === void 0 ? void 0 : _a.removeField("cameraID");
3202
+ (_b = this._main.getStorageManager()) === null || _b === void 0 ? void 0 : _b.removeField("microphoneID");
3203
+ }
3204
+ messSavedDevices() {
3205
+ var _a, _b;
3206
+ (_a = this._main.getStorageManager()) === null || _a === void 0 ? void 0 : _a.saveField("cameraID", "a");
3207
+ (_b = this._main.getStorageManager()) === null || _b === void 0 ? void 0 : _b.saveField("microphoneID", "b");
3208
+ }
3136
3209
  muteMicrophone(shouldMute) {
3137
3210
  if (this._isMicrophoneMuted === shouldMute) {
3138
3211
  return;
@@ -3212,16 +3285,105 @@
3212
3285
  getPlayer() {
3213
3286
  return this._selectedPlayer;
3214
3287
  }
3288
+ stopCameraStream() {
3289
+ var _a, _b;
3290
+ if (this._stream) {
3291
+ this._stream.getTracks().forEach(track => track.stop());
3292
+ const videoElement = (_b = (_a = this._main.getStageController()) === null || _a === void 0 ? void 0 : _a.getScreenElement()) === null || _b === void 0 ? void 0 : _b.getVideoElement();
3293
+ if (videoElement) {
3294
+ videoElement.srcObject = null;
3295
+ }
3296
+ this._soundMeter.detach();
3297
+ this._stream = null;
3298
+ }
3299
+ }
3300
+ forceStopAllStreams() {
3301
+ var _a, _b;
3302
+ console.log("Force stopping all streams...");
3303
+ if (this._peerConnection) {
3304
+ try {
3305
+ const senders = this._peerConnection.getSenders();
3306
+ senders.forEach(sender => {
3307
+ var _a;
3308
+ try {
3309
+ if (sender.track) {
3310
+ sender.track.enabled = false;
3311
+ sender.track.stop();
3312
+ (_a = this._peerConnection) === null || _a === void 0 ? void 0 : _a.removeTrack(sender);
3313
+ }
3314
+ } catch (e) {
3315
+ console.error('Error stopping sender track:', e);
3316
+ }
3317
+ });
3318
+ this._peerConnection.close();
3319
+ this._peerConnection = null;
3320
+ } catch (e) {
3321
+ console.error('Error closing peer connection:', e);
3322
+ }
3323
+ }
3324
+ try {
3325
+ const videoElement = (_b = (_a = this._main.getStageController()) === null || _a === void 0 ? void 0 : _a.getScreenElement()) === null || _b === void 0 ? void 0 : _b.getVideoElement();
3326
+ if (videoElement && videoElement.srcObject instanceof MediaStream) {
3327
+ const videoTracks = videoElement.srcObject.getTracks();
3328
+ videoTracks.forEach(track => {
3329
+ try {
3330
+ track.enabled = false;
3331
+ track.stop();
3332
+ } catch (e) {
3333
+ console.error('Error stopping video element track:', e);
3334
+ }
3335
+ });
3336
+ videoElement.srcObject = null;
3337
+ videoElement.removeAttribute('src');
3338
+ videoElement.load();
3339
+ }
3340
+ } catch (e) {
3341
+ console.error('Error cleaning video element:', e);
3342
+ }
3343
+ if (this._stream) {
3344
+ try {
3345
+ const tracks = this._stream.getTracks();
3346
+ console.log(`Stopping ${tracks.length} tracks from main stream`);
3347
+ tracks.forEach(track => {
3348
+ try {
3349
+ console.log(`Stopping ${track.kind} track, enabled: ${track.enabled}, state: ${track.readyState}`);
3350
+ track.enabled = false;
3351
+ track.stop();
3352
+ console.log(`Track after stop - state: ${track.readyState}`);
3353
+ } catch (e) {
3354
+ console.error(`Error stopping ${track.kind} track:`, e);
3355
+ }
3356
+ });
3357
+ this._stream = null;
3358
+ } catch (e) {
3359
+ console.error('Error stopping main stream:', e);
3360
+ }
3361
+ }
3362
+ console.log("All streams should be stopped now");
3363
+ }
3215
3364
  destroy() {
3216
- var _a;
3365
+ console.log("Starting destroy process...");
3366
+ this.forceStopAllStreams();
3367
+ if (this._soundMeter) {
3368
+ this._soundMeter.detach();
3369
+ }
3217
3370
  this._pendingMicrophoneState = null;
3218
- this.closeStream();
3219
- (_a = this._selectedPlayer) === null || _a === void 0 ? void 0 : _a.clear();
3220
- this._selectedPlayer = null;
3221
- this._main.removeEventListener("serverConnect", this.onServerConnect);
3222
- document.removeEventListener("visibilitychange", this.visibilityChange);
3223
- window.removeEventListener("blur", this.onWindowBlur);
3224
- window.removeEventListener("focus", this.onWindowFocus);
3371
+ this._cameraList = new InputDeviceList();
3372
+ this._microphoneList = new InputDeviceList();
3373
+ this._permissionChecked = false;
3374
+ this._isWindowActive = false;
3375
+ this._isMicrophoneMuted = false;
3376
+ try {
3377
+ this._main.removeEventListener("serverConnect", this.onServerConnect);
3378
+ this._main.removeEventListener("serverDisconnect", this.onServerDisconnect);
3379
+ document.removeEventListener("visibilitychange", this.visibilityChange);
3380
+ window.removeEventListener("blur", this.onWindowBlur);
3381
+ window.removeEventListener("focus", this.onWindowFocus);
3382
+ } catch (e) {
3383
+ console.error('Error removing event listeners:', e);
3384
+ }
3385
+ this._publishState = exports.PublishState.NOT_INITIALIZED;
3386
+ console.log("Destroy process completed");
3225
3387
  }
3226
3388
  }
3227
3389
 
@@ -3523,8 +3685,8 @@
3523
3685
  constructor(streamConfig, autoInitialize = false) {
3524
3686
  super();
3525
3687
  this.DEV_MODE = true;
3526
- this.STREAMER_VERSION = "0.9.0-beta.3";
3527
- this.COMPILE_DATE = "12/5/2024, 2:36:49 PM";
3688
+ this.STREAMER_VERSION = "0.9.0-beta.4";
3689
+ this.COMPILE_DATE = "12/7/2024, 6:37:54 PM";
3528
3690
  this.STREAMER_BRANCH = "Experimental";
3529
3691
  this.STREAMER_PROTOCOL_VERSION = 1;
3530
3692
  this._initialized = false;
@@ -3680,6 +3842,14 @@
3680
3842
  var _a, _b;
3681
3843
  return (_b = (_a = this._playbackController) === null || _a === void 0 ? void 0 : _a.publish(streamKey)) !== null && _b !== void 0 ? _b : false;
3682
3844
  }
3845
+ clearSavedDevices() {
3846
+ var _a;
3847
+ return (_a = this._playbackController) === null || _a === void 0 ? void 0 : _a.clearSavedDevices();
3848
+ }
3849
+ messSavedDevices() {
3850
+ var _a;
3851
+ return (_a = this._playbackController) === null || _a === void 0 ? void 0 : _a.messSavedDevices();
3852
+ }
3683
3853
  isStreamReady() {
3684
3854
  var _a, _b;
3685
3855
  return (_b = (_a = this._playbackController) === null || _a === void 0 ? void 0 : _a.isStreamReady()) !== null && _b !== void 0 ? _b : false;
@@ -3818,8 +3988,8 @@
3818
3988
  this._initialized = false;
3819
3989
  this._isRemoved = true;
3820
3990
  (_b = (_a = this._networkController) === null || _a === void 0 ? void 0 : _a.getConnection()) === null || _b === void 0 ? void 0 : _b.destroy();
3821
- (_c = this._stageController) === null || _c === void 0 ? void 0 : _c.destroy();
3822
- (_d = this._playbackController) === null || _d === void 0 ? void 0 : _d.destroy();
3991
+ (_c = this._playbackController) === null || _c === void 0 ? void 0 : _c.destroy();
3992
+ (_d = this._stageController) === null || _d === void 0 ? void 0 : _d.destroy();
3823
3993
  this.removeAllEventListeners();
3824
3994
  }
3825
3995
  }