@cloudflare/realtimekit-react-native 0.2.1 → 0.2.2-staging.2

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.
Files changed (44) hide show
  1. package/android/build.gradle +0 -2
  2. package/android/src/main/java/com/cloudflare/realtimekit/CoreModule.java +19 -0
  3. package/android/src/main/java/com/cloudflare/realtimekit/ForegroundService.java +2 -4
  4. package/android/src/main/java/com/cloudflare/realtimekit/RTKHelperModule.java +1 -2
  5. package/android/src/main/java/com/cloudflare/realtimekit/RTKLogger.java +116 -0
  6. package/android/src/main/java/com/cloudflare/realtimekit/incallmanager/AppRTCBluetoothManager.java +75 -74
  7. package/android/src/main/java/com/cloudflare/realtimekit/incallmanager/AppRTCUtils.java +10 -9
  8. package/android/src/main/java/com/cloudflare/realtimekit/incallmanager/InCallManagerModule.java +175 -872
  9. package/android/src/main/java/com/cloudflare/realtimekit/incallmanager/InCallProximityManager.java +9 -8
  10. package/android/src/main/java/com/cloudflare/realtimekit/incallmanager/InCallWakeLockUtils.java +8 -7
  11. package/ios/BroadcastEventEmitter.m +9 -0
  12. package/ios/Core.h +9 -1
  13. package/ios/Core.m +42 -0
  14. package/ios/RNInCallManager.m +639 -700
  15. package/ios/RTKLogger.h +51 -0
  16. package/ios/RTKLogger.m +107 -0
  17. package/ios/RTKRNBackgroundTimer.m +8 -7
  18. package/ios/RTKRNPermissionHandlerNotifications.m +12 -0
  19. package/ios/RTKRNPermissions.m +24 -1
  20. package/ios/RTKScreensharePickerView.m +6 -0
  21. package/ios/screenshare/RTKScreenshareHandler.swift +1 -1
  22. package/ios/screenshare/RTKScreenshareUploader.swift +3 -3
  23. package/ios/screenshare/RTKSocketConnection.swift +8 -8
  24. package/lib/commonjs/LocalMediaHandler.js +82 -24
  25. package/lib/commonjs/LocalMediaHandler.js.map +1 -1
  26. package/lib/commonjs/LocalMediaUtils.js +60 -5
  27. package/lib/commonjs/LocalMediaUtils.js.map +1 -1
  28. package/lib/commonjs/NativeAudioManager.js +7 -3
  29. package/lib/commonjs/NativeAudioManager.js.map +1 -1
  30. package/lib/commonjs/utils/version.js +1 -1
  31. package/lib/commonjs/utils/version.js.map +1 -1
  32. package/lib/module/LocalMediaHandler.js +82 -24
  33. package/lib/module/LocalMediaHandler.js.map +1 -1
  34. package/lib/module/LocalMediaUtils.js +60 -5
  35. package/lib/module/LocalMediaUtils.js.map +1 -1
  36. package/lib/module/NativeAudioManager.js +7 -3
  37. package/lib/module/NativeAudioManager.js.map +1 -1
  38. package/lib/module/utils/version.js +1 -1
  39. package/lib/module/utils/version.js.map +1 -1
  40. package/lib/typescript/LocalMediaHandler.d.ts +1 -0
  41. package/lib/typescript/LocalMediaUtils.d.ts +1 -0
  42. package/lib/typescript/NativeAudioManager.d.ts +1 -0
  43. package/lib/typescript/utils/version.d.ts +1 -1
  44. package/package.json +2 -4
@@ -1 +1 @@
1
- {"version":3,"names":["_reactNative","require","_reactNativeWebrtc","_LocalMediaError","_interopRequireDefault","_NativeAudioManager","e","__esModule","default","_classPrivateFieldInitSpec","t","a","_checkPrivateRedeclaration","set","has","TypeError","_classPrivateFieldGet","s","get","_assertClassBrand","_classPrivateFieldSet","r","n","arguments","length","LogBox","ignoreLogs","VIDEO_CONSTRAINTS","exports","qvga","width","ideal","height","vga","hd","hd_cropped","_availableDevices","WeakMap","_nativeEventEmitter","LocalMediaUtils","constructor","availableDevices","NativeEventEmitter","NativeModules","InCallManager","init","availableVideoDevices","enumerateVideoDevices","availableAudioDevices","enumerateAudioDevices","concat","destruct","removeAllListeners","isDeviceListAvailable","deviceMem","videoDevices","mediaDevices","enumerateDevices","filter","d","kind","facing","error","audioDevices","earpiece","connected","haveMic","speaker","bluetooth","wired","isWiredHeadphonesConnected","NativeAudioManager","getIsWiredHeadsetPluggedIn","isBluetoothHeadsetConnected","resp","Object","keys","map","audioDevice","audioDeviceProps","deviceId","label","getVideoConstraints","options","constraints","videoDeviceId","videoTrackConstraints","facingMode","frameRate","max","video","getUserMediaWithTimeout","timeout","getUserMedia","Promise","race","_resolve","reject","setTimeout","LocalMediaError","err","getAudioTrack","mediaStream","audio","getAudioTracks","getVideoTrack","getVideoTracks","getScreenShareTracks","stream","getDisplayMedia","getAudioAndVideoTrack","audioTrack","videoTrack","onDeviceChange","callback","onChange","deviceData","checkDeviceId","_id","toLowerCase","includes","previouslyAvailableDevices","device","previouslyAvailableDeviceIds","len","availableAudioDeviceList","currentlyAvailableDevices","currentlyAvailableDeviceIds","changedDevices","added","removed","repopulateAvailableDevices","then","listenerCount","addListener","chooseAudioRoute","route","getAvailableDevicesByKind","getDeviceById","find","getAudioDevices","getVideoDevices","getSpeakerDevices","speakerDevices"],"sources":["LocalMediaUtils.ts"],"sourcesContent":["import { NativeEventEmitter, NativeModules, LogBox } from 'react-native';\nimport { mediaDevices, MediaStream } from '@cloudflare/react-native-webrtc';\nimport LocalMediaError from './LocalMediaError';\nimport {\n ConstrainDouble,\n RealtimeKitMediaStreamConstraints,\n RealtimeKitMediaTrackConstraints,\n MediaDeviceInfo,\n} from './LocalMediaInterfaces';\nimport NativeAudioManager from './NativeAudioManager';\nLogBox.ignoreLogs(['new NativeEventEmitter']);\nexport interface LocalAudioOptions {\n // Disables all audio processing\n disableAP?: boolean;\n\n // Disables Acoustic Echo Cancellation\n disableAEC?: boolean;\n\n // Disables Noise Suppression\n disableNS?: boolean;\n\n // Disables Automatic Gain Control\n disableAGC?: boolean;\n\n // Disables Highpass Filter\n disableHPF?: boolean;\n}\n\nexport const VIDEO_CONSTRAINTS = {\n qvga: { width: { ideal: 320 }, height: { ideal: 240 } },\n vga: { width: { ideal: 640 }, height: { ideal: 480 } },\n hd: { width: { ideal: 1280 }, height: { ideal: 720 } },\n hd_cropped: { width: { ideal: 900 }, height: { ideal: 720 } },\n};\n\n/**\n * To initialize an instance of this class, use the\n * `.init()` static method.\n */\nexport default class LocalMediaUtils {\n #availableDevices: MediaDeviceInfo[];\n\n #nativeEventEmitter: NativeEventEmitter;\n\n private constructor(availableDevices: MediaDeviceInfo[]) {\n this.#availableDevices = availableDevices;\n this.#nativeEventEmitter = new NativeEventEmitter(\n NativeModules.InCallManager\n );\n }\n\n public static async init() {\n const availableVideoDevices = await LocalMediaUtils.enumerateVideoDevices();\n const availableAudioDevices = await LocalMediaUtils.enumerateAudioDevices();\n return new LocalMediaUtils(\n availableAudioDevices.concat(availableVideoDevices)\n );\n }\n\n public async destruct() {\n this.#nativeEventEmitter.removeAllListeners('onAudioDeviceChanged');\n }\n\n public static isDeviceListAvailable() {\n return true;\n }\n\n private static async enumerateVideoDevices(): Promise<MediaDeviceInfo[]> {\n try {\n const deviceMem = {};\n const videoDevices =\n (await mediaDevices.enumerateDevices()) as MediaDeviceInfo[];\n return videoDevices.filter((d) => {\n if (d.kind === 'videoinput' && !deviceMem[d.facing]) {\n deviceMem[d.facing] = true;\n return d;\n }\n return false;\n });\n } catch (error) {\n return [];\n }\n }\n\n private static async enumerateAudioDevices(): Promise<MediaDeviceInfo[]> {\n let audioDevices = {\n earpiece: {\n connected: true,\n haveMic: true,\n },\n speaker: {\n connected: true,\n haveMic: true,\n },\n bluetooth: {\n connected: false,\n haveMic: false,\n },\n wired: {\n connected: false,\n haveMic: false,\n },\n };\n const isWiredHeadphonesConnected =\n await NativeAudioManager.getIsWiredHeadsetPluggedIn();\n audioDevices.wired = isWiredHeadphonesConnected\n ? {\n connected: true,\n haveMic: true,\n }\n : {\n connected: false,\n haveMic: false,\n };\n const isBluetoothHeadsetConnected =\n await NativeAudioManager.isBluetoothHeadsetConnected();\n audioDevices.bluetooth = isBluetoothHeadsetConnected\n ? {\n connected: true,\n haveMic: true,\n }\n : {\n connected: false,\n haveMic: false,\n };\n const resp = Object.keys(audioDevices)\n .map((audioDevice) => {\n const audioDeviceProps = audioDevices[audioDevice];\n return {\n ...audioDeviceProps,\n deviceId: audioDevice,\n label: audioDevice,\n kind: 'audioinput',\n };\n })\n .filter((audioDevice) => audioDevice.connected);\n return resp as MediaDeviceInfo[];\n }\n\n public static getVideoConstraints(options?: {\n videoDeviceId?: string;\n videoTrackConstraints?: boolean | RealtimeKitMediaTrackConstraints;\n facingMode?: string;\n frameRate?: ConstrainDouble;\n }) {\n const constraints: RealtimeKitMediaStreamConstraints = {};\n const {\n videoDeviceId,\n videoTrackConstraints,\n facingMode = 'user',\n frameRate = { ideal: 24, max: 30 },\n } = options;\n\n constraints.video = videoTrackConstraints || VIDEO_CONSTRAINTS.vga;\n if (typeof constraints.video === 'boolean') {\n return constraints;\n }\n\n constraints.video.deviceId = videoDeviceId;\n constraints.video.facingMode = facingMode;\n constraints.video.frameRate = frameRate;\n return constraints;\n }\n\n private static async getUserMediaWithTimeout(\n constraints: RealtimeKitMediaStreamConstraints = {},\n timeout: number = 0\n ) {\n try {\n if (!timeout) {\n return await mediaDevices.getUserMedia(constraints);\n }\n\n // NOTE(roerohan): The await is required to catch errors (if any).\n return Promise.race<Promise<unknown>>([\n mediaDevices.getUserMedia(constraints),\n\n new Promise<MediaStream>((_resolve, reject) => {\n setTimeout(\n () =>\n reject(\n new LocalMediaError(\n 'Get user media timed out',\n 'ERR_GUM_TIMEOUT'\n )\n ),\n timeout\n );\n }),\n ]);\n } catch (err) {\n throw err;\n }\n }\n\n public static async getAudioTrack() {\n const mediaStream = (await LocalMediaUtils.getUserMediaWithTimeout({\n audio: true,\n timeout: 5000,\n })) as MediaStream;\n return mediaStream.getAudioTracks()[0];\n }\n\n public static async getVideoTrack(\n constraints: RealtimeKitMediaStreamConstraints\n ) {\n const mediaStream = (await LocalMediaUtils.getUserMediaWithTimeout({\n ...constraints,\n timeout: 5000,\n })) as MediaStream;\n return mediaStream.getVideoTracks()[0];\n }\n\n public static async getScreenShareTracks() {\n /**\n * getDisplayMedia is not defined on type MediaDevices.\n * Need to update this when a fix\n * is made: https://github.com/microsoft/TypeScript/issues/33232\n */\n const stream: MediaStream =\n (await mediaDevices.getDisplayMedia()) as MediaStream;\n return {\n video: stream.getVideoTracks()[0],\n audio: stream.getAudioTracks()[0],\n };\n }\n\n public static async getAudioAndVideoTrack(\n constraints: RealtimeKitMediaStreamConstraints\n ) {\n try {\n const mediaStream = (await LocalMediaUtils.getUserMediaWithTimeout({\n ...constraints,\n timeout: 5000,\n })) as MediaStream;\n return {\n audioTrack: mediaStream.getAudioTracks()[0],\n videoTrack: mediaStream.getVideoTracks()[0],\n };\n } catch (err) {\n throw err;\n }\n }\n\n public onDeviceChange(\n callback: (\n changedDevices: {\n added: MediaDeviceInfo[];\n removed: MediaDeviceInfo[];\n },\n forceDeviceChange?: boolean\n ) => void\n ) {\n const onChange = async (deviceData) => {\n const checkDeviceId = (_id: string) => {\n if (_id.toLowerCase().includes('speaker')) return 'speaker';\n else return _id;\n };\n const previouslyAvailableDevices = this.#availableDevices.filter(\n (device) =>\n device.kind === 'audioinput' || device.kind === 'audiooutput'\n );\n const previouslyAvailableDeviceIds = previouslyAvailableDevices.map(\n (device) => checkDeviceId(device.deviceId)\n );\n const len = deviceData.availableAudioDeviceList.length;\n if (len === 0) {\n const currentlyAvailableDevices =\n await LocalMediaUtils.enumerateAudioDevices();\n const currentlyAvailableDeviceIds = currentlyAvailableDevices.map(\n (device) => checkDeviceId(device.deviceId)\n );\n\n const changedDevices = {\n added: currentlyAvailableDevices.filter(\n (device) =>\n !previouslyAvailableDeviceIds.includes(\n checkDeviceId(device.deviceId)\n )\n ),\n removed: previouslyAvailableDevices.filter(\n (device) => !currentlyAvailableDeviceIds.includes(device.deviceId)\n ),\n };\n this.repopulateAvailableDevices().then(() => {\n if (changedDevices.added.length || changedDevices.removed.length) {\n callback(changedDevices, false);\n }\n });\n } else {\n const currentlyAvailableDevices =\n await LocalMediaUtils.enumerateAudioDevices();\n const currentlyAvailableDeviceIds = currentlyAvailableDevices.map(\n (device) => checkDeviceId(device.deviceId)\n );\n const availableAudioDevices =\n await LocalMediaUtils.enumerateAudioDevices();\n\n const changedDevices = {\n added: availableAudioDevices.filter(\n (device) =>\n !previouslyAvailableDeviceIds.includes(\n checkDeviceId(device.deviceId)\n )\n ),\n removed: previouslyAvailableDevices.filter(\n (device) => !currentlyAvailableDeviceIds.includes(device.deviceId)\n ),\n };\n\n this.repopulateAvailableDevices().then(() => {\n if (changedDevices.added.length || changedDevices.removed.length) {\n callback(changedDevices, false);\n }\n });\n }\n };\n if (this.#nativeEventEmitter.listenerCount('onAudioDeviceChanged') === 0) {\n this.#nativeEventEmitter.addListener('onAudioDeviceChanged', onChange);\n }\n }\n\n public async repopulateAvailableDevices() {\n const videoDevices = await LocalMediaUtils.enumerateVideoDevices();\n const audioDevices = await LocalMediaUtils.enumerateAudioDevices();\n this.#availableDevices = videoDevices.concat(audioDevices);\n }\n\n public async chooseAudioRoute(route: String) {\n return await NativeAudioManager.chooseAudioRoute(route);\n }\n\n public get availableDevices() {\n return this.#availableDevices;\n }\n\n public getAvailableDevicesByKind(kind: string) {\n return this.#availableDevices.filter((device) => device.kind === kind);\n }\n\n public getDeviceById(\n deviceId: string,\n kind: 'audioinput' | 'audiooutput' | 'videoinput'\n ) {\n return this.#availableDevices.find(\n (device) => device.deviceId === deviceId && device.kind === kind\n );\n }\n\n /**\n * Returns all audio input devices (microphone devices).\n */\n public getAudioDevices() {\n return this.getAvailableDevicesByKind('audioinput');\n }\n\n /**\n * Returns all video input devices.\n */\n public getVideoDevices() {\n return this.getAvailableDevicesByKind('videoinput');\n }\n\n /**\n * Returns all audio output devices (speaker devices).\n */\n public getSpeakerDevices() {\n const speakerDevices = this.#availableDevices;\n // In Mobile, speaker devices are the same as audio input devices\n return speakerDevices\n .filter((device) => device.kind === 'audioinput')\n .map((device) => ({\n ...device,\n deviceId: device.deviceId,\n label: device.label,\n kind: 'audiooutput',\n }));\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_reactNative","require","_reactNativeWebrtc","_LocalMediaError","_interopRequireDefault","_NativeAudioManager","e","__esModule","default","_classPrivateFieldInitSpec","t","a","_checkPrivateRedeclaration","set","has","TypeError","_classPrivateFieldGet","s","get","_assertClassBrand","_classPrivateFieldSet","r","n","arguments","length","LogBox","ignoreLogs","VIDEO_CONSTRAINTS","exports","qvga","width","ideal","height","vga","hd","hd_cropped","_availableDevices","WeakMap","_nativeEventEmitter","_previouslySelectedDevice","LocalMediaUtils","constructor","availableDevices","NativeEventEmitter","NativeModules","InCallManager","init","availableVideoDevices","enumerateVideoDevices","availableAudioDevices","enumerateAudioDevices","concat","destruct","removeAllListeners","isDeviceListAvailable","deviceMem","videoDevices","mediaDevices","enumerateDevices","filter","d","kind","facing","error","audioDevices","earpiece","connected","haveMic","speaker","bluetooth","wired","isWiredHeadphonesConnected","NativeAudioManager","getIsWiredHeadsetPluggedIn","isBluetoothHeadsetConnected","resp","Object","keys","map","audioDevice","audioDeviceProps","deviceId","label","getVideoConstraints","options","constraints","videoDeviceId","videoTrackConstraints","facingMode","frameRate","max","video","getUserMediaWithTimeout","timeout","getUserMedia","Promise","race","_resolve","reject","setTimeout","LocalMediaError","err","getAudioTrack","mediaStream","audio","getAudioTracks","getVideoTrack","getVideoTracks","getScreenShareTracks","stream","getDisplayMedia","getAudioAndVideoTrack","audioTrack","videoTrack","onDeviceChange","callback","onChange","deviceData","checkDeviceId","_id","toLowerCase","includes","selectedDevice","selectedAudioDevice","hasSelectedDeviceChanged","isFirstDeviceEvent","previouslyAvailableDevices","device","previouslyAvailableDeviceIds","availableDeviceListFromEvent","len","availableAudioDeviceList","JSON","parse","currentlyAvailableDevices","currentlyAvailableDeviceIds","changedDevices","added","removed","hasAvailableListChanged","every","repopulateAvailableDevices","then","shouldFireCallback","listenerCount","addListener","chooseAudioRoute","route","getAvailableDevicesByKind","getDeviceById","normalizedDeviceId","find","deviceIdLower","getAudioDevices","getVideoDevices","getSpeakerDevices","speakerDevices"],"sources":["LocalMediaUtils.ts"],"sourcesContent":["import { NativeEventEmitter, NativeModules, LogBox } from 'react-native';\nimport { mediaDevices, MediaStream } from '@cloudflare/react-native-webrtc';\nimport LocalMediaError from './LocalMediaError';\nimport {\n ConstrainDouble,\n RealtimeKitMediaStreamConstraints,\n RealtimeKitMediaTrackConstraints,\n MediaDeviceInfo,\n} from './LocalMediaInterfaces';\nimport NativeAudioManager from './NativeAudioManager';\nLogBox.ignoreLogs(['new NativeEventEmitter']);\nexport interface LocalAudioOptions {\n // Disables all audio processing\n disableAP?: boolean;\n\n // Disables Acoustic Echo Cancellation\n disableAEC?: boolean;\n\n // Disables Noise Suppression\n disableNS?: boolean;\n\n // Disables Automatic Gain Control\n disableAGC?: boolean;\n\n // Disables Highpass Filter\n disableHPF?: boolean;\n}\n\nexport const VIDEO_CONSTRAINTS = {\n qvga: { width: { ideal: 320 }, height: { ideal: 240 } },\n vga: { width: { ideal: 640 }, height: { ideal: 480 } },\n hd: { width: { ideal: 1280 }, height: { ideal: 720 } },\n hd_cropped: { width: { ideal: 900 }, height: { ideal: 720 } },\n};\n\n/**\n * To initialize an instance of this class, use the\n * `.init()` static method.\n */\nexport default class LocalMediaUtils {\n #availableDevices: MediaDeviceInfo[];\n\n #nativeEventEmitter: NativeEventEmitter;\n\n #previouslySelectedDevice: string | null = null;\n\n private constructor(availableDevices: MediaDeviceInfo[]) {\n this.#availableDevices = availableDevices;\n this.#nativeEventEmitter = new NativeEventEmitter(\n NativeModules.InCallManager\n );\n }\n\n public static async init() {\n const availableVideoDevices = await LocalMediaUtils.enumerateVideoDevices();\n const availableAudioDevices = await LocalMediaUtils.enumerateAudioDevices();\n return new LocalMediaUtils(\n availableAudioDevices.concat(availableVideoDevices)\n );\n }\n\n public async destruct() {\n this.#nativeEventEmitter.removeAllListeners('onAudioDeviceChanged');\n }\n\n public static isDeviceListAvailable() {\n return true;\n }\n\n private static async enumerateVideoDevices(): Promise<MediaDeviceInfo[]> {\n try {\n const deviceMem = {};\n const videoDevices =\n (await mediaDevices.enumerateDevices()) as MediaDeviceInfo[];\n return videoDevices.filter((d) => {\n if (d.kind === 'videoinput' && !deviceMem[d.facing]) {\n deviceMem[d.facing] = true;\n return d;\n }\n return false;\n });\n } catch (error) {\n return [];\n }\n }\n\n private static async enumerateAudioDevices(): Promise<MediaDeviceInfo[]> {\n let audioDevices = {\n earpiece: {\n connected: true,\n haveMic: true,\n },\n speaker: {\n connected: true,\n haveMic: true,\n },\n bluetooth: {\n connected: false,\n haveMic: false,\n },\n wired: {\n connected: false,\n haveMic: false,\n },\n };\n const isWiredHeadphonesConnected =\n await NativeAudioManager.getIsWiredHeadsetPluggedIn();\n audioDevices.wired = isWiredHeadphonesConnected\n ? {\n connected: true,\n haveMic: true,\n }\n : {\n connected: false,\n haveMic: false,\n };\n const isBluetoothHeadsetConnected =\n await NativeAudioManager.isBluetoothHeadsetConnected();\n audioDevices.bluetooth = isBluetoothHeadsetConnected\n ? {\n connected: true,\n haveMic: true,\n }\n : {\n connected: false,\n haveMic: false,\n };\n const resp = Object.keys(audioDevices)\n .map((audioDevice) => {\n const audioDeviceProps = audioDevices[audioDevice];\n return {\n ...audioDeviceProps,\n deviceId: audioDevice,\n label: audioDevice,\n kind: 'audioinput',\n };\n })\n .filter((audioDevice) => audioDevice.connected);\n return resp as MediaDeviceInfo[];\n }\n\n public static getVideoConstraints(options?: {\n videoDeviceId?: string;\n videoTrackConstraints?: boolean | RealtimeKitMediaTrackConstraints;\n facingMode?: string;\n frameRate?: ConstrainDouble;\n }) {\n const constraints: RealtimeKitMediaStreamConstraints = {};\n const {\n videoDeviceId,\n videoTrackConstraints,\n facingMode = 'user',\n frameRate = { ideal: 24, max: 30 },\n } = options;\n\n constraints.video = videoTrackConstraints || VIDEO_CONSTRAINTS.vga;\n if (typeof constraints.video === 'boolean') {\n return constraints;\n }\n\n constraints.video.deviceId = videoDeviceId;\n constraints.video.facingMode = facingMode;\n constraints.video.frameRate = frameRate;\n return constraints;\n }\n\n private static async getUserMediaWithTimeout(\n constraints: RealtimeKitMediaStreamConstraints = {},\n timeout: number = 0\n ) {\n try {\n if (!timeout) {\n return await mediaDevices.getUserMedia(constraints);\n }\n\n // NOTE(roerohan): The await is required to catch errors (if any).\n return Promise.race<Promise<unknown>>([\n mediaDevices.getUserMedia(constraints),\n\n new Promise<MediaStream>((_resolve, reject) => {\n setTimeout(\n () =>\n reject(\n new LocalMediaError(\n 'Get user media timed out',\n 'ERR_GUM_TIMEOUT'\n )\n ),\n timeout\n );\n }),\n ]);\n } catch (err) {\n throw err;\n }\n }\n\n public static async getAudioTrack() {\n const mediaStream = (await LocalMediaUtils.getUserMediaWithTimeout({\n audio: true,\n timeout: 5000,\n })) as MediaStream;\n return mediaStream.getAudioTracks()[0];\n }\n\n public static async getVideoTrack(\n constraints: RealtimeKitMediaStreamConstraints\n ) {\n const mediaStream = (await LocalMediaUtils.getUserMediaWithTimeout({\n ...constraints,\n timeout: 5000,\n })) as MediaStream;\n return mediaStream.getVideoTracks()[0];\n }\n\n public static async getScreenShareTracks() {\n /**\n * getDisplayMedia is not defined on type MediaDevices.\n * Need to update this when a fix\n * is made: https://github.com/microsoft/TypeScript/issues/33232\n */\n const stream: MediaStream =\n (await mediaDevices.getDisplayMedia()) as MediaStream;\n return {\n video: stream.getVideoTracks()[0],\n audio: stream.getAudioTracks()[0],\n };\n }\n\n public static async getAudioAndVideoTrack(\n constraints: RealtimeKitMediaStreamConstraints\n ) {\n try {\n const mediaStream = (await LocalMediaUtils.getUserMediaWithTimeout({\n ...constraints,\n timeout: 5000,\n })) as MediaStream;\n return {\n audioTrack: mediaStream.getAudioTracks()[0],\n videoTrack: mediaStream.getVideoTracks()[0],\n };\n } catch (err) {\n throw err;\n }\n }\n\n public onDeviceChange(\n callback: (\n changedDevices: {\n added: MediaDeviceInfo[];\n removed: MediaDeviceInfo[];\n selectedDevice?: string;\n },\n forceDeviceChange?: boolean\n ) => void\n ) {\n const onChange = async (deviceData) => {\n const checkDeviceId = (_id: string) => {\n if (_id.toLowerCase().includes('speaker')) return 'speaker';\n else return _id;\n };\n\n // Extract selected device from event\n const selectedDevice = deviceData.selectedAudioDevice;\n const hasSelectedDeviceChanged =\n selectedDevice &&\n this.#previouslySelectedDevice !== null &&\n selectedDevice !== this.#previouslySelectedDevice;\n\n // On first event, we need to initialize previouslySelectedDevice and fire callback\n const isFirstDeviceEvent =\n selectedDevice && this.#previouslySelectedDevice === null;\n\n // Update previouslySelectedDevice IMMEDIATELY after detection to avoid race conditions\n // This must happen BEFORE any async operations\n if (selectedDevice) {\n this.#previouslySelectedDevice = selectedDevice;\n }\n\n const previouslyAvailableDevices = this.#availableDevices.filter(\n (device) =>\n device.kind === 'audioinput' || device.kind === 'audiooutput'\n );\n const previouslyAvailableDeviceIds = previouslyAvailableDevices.map(\n (device) => checkDeviceId(device.deviceId)\n );\n\n // Parse available device list from event to detect list changes\n let availableDeviceListFromEvent: string[] = [];\n const len = deviceData.availableAudioDeviceList.length;\n if (typeof deviceData.availableAudioDeviceList === 'string') {\n try {\n availableDeviceListFromEvent = JSON.parse(\n deviceData.availableAudioDeviceList\n );\n } catch (e) {\n // If parsing fails, fall back to empty array\n availableDeviceListFromEvent = [];\n }\n }\n if (len === 0) {\n const currentlyAvailableDevices =\n await LocalMediaUtils.enumerateAudioDevices();\n const currentlyAvailableDeviceIds = currentlyAvailableDevices.map(\n (device) => checkDeviceId(device.deviceId)\n );\n\n const changedDevices = {\n added: currentlyAvailableDevices.filter(\n (device) =>\n !previouslyAvailableDeviceIds.includes(\n checkDeviceId(device.deviceId)\n )\n ),\n removed: previouslyAvailableDevices.filter(\n (device) => !currentlyAvailableDeviceIds.includes(device.deviceId)\n ),\n selectedDevice: selectedDevice,\n };\n\n // Check if available device list changed\n const hasAvailableListChanged =\n availableDeviceListFromEvent.length > 0 &&\n (availableDeviceListFromEvent.length !==\n previouslyAvailableDeviceIds.length ||\n !availableDeviceListFromEvent.every((device) =>\n previouslyAvailableDeviceIds.includes(device)\n ));\n\n this.repopulateAvailableDevices().then(() => {\n const shouldFireCallback =\n changedDevices.added.length ||\n changedDevices.removed.length ||\n hasSelectedDeviceChanged ||\n isFirstDeviceEvent ||\n hasAvailableListChanged;\n\n if (shouldFireCallback) {\n callback(changedDevices, false);\n }\n });\n } else {\n const currentlyAvailableDevices =\n await LocalMediaUtils.enumerateAudioDevices();\n const currentlyAvailableDeviceIds = currentlyAvailableDevices.map(\n (device) => checkDeviceId(device.deviceId)\n );\n const availableAudioDevices =\n await LocalMediaUtils.enumerateAudioDevices();\n\n const changedDevices = {\n added: availableAudioDevices.filter(\n (device) =>\n !previouslyAvailableDeviceIds.includes(\n checkDeviceId(device.deviceId)\n )\n ),\n removed: previouslyAvailableDevices.filter(\n (device) => !currentlyAvailableDeviceIds.includes(device.deviceId)\n ),\n selectedDevice: selectedDevice,\n };\n\n // Check if available device list changed\n const hasAvailableListChanged =\n availableDeviceListFromEvent.length > 0 &&\n (availableDeviceListFromEvent.length !==\n previouslyAvailableDeviceIds.length ||\n !availableDeviceListFromEvent.every((device) =>\n previouslyAvailableDeviceIds.includes(device)\n ));\n\n this.repopulateAvailableDevices().then(() => {\n const shouldFireCallback =\n changedDevices.added.length ||\n changedDevices.removed.length ||\n hasSelectedDeviceChanged ||\n isFirstDeviceEvent ||\n hasAvailableListChanged;\n\n if (shouldFireCallback) {\n callback(changedDevices, false);\n }\n });\n }\n };\n if (this.#nativeEventEmitter.listenerCount('onAudioDeviceChanged') === 0) {\n this.#nativeEventEmitter.addListener('onAudioDeviceChanged', onChange);\n }\n }\n\n public async repopulateAvailableDevices() {\n const videoDevices = await LocalMediaUtils.enumerateVideoDevices();\n const audioDevices = await LocalMediaUtils.enumerateAudioDevices();\n this.#availableDevices = videoDevices.concat(audioDevices);\n }\n\n public async chooseAudioRoute(route: String) {\n return await NativeAudioManager.chooseAudioRoute(route);\n }\n\n public get availableDevices() {\n return this.#availableDevices;\n }\n\n public getAvailableDevicesByKind(kind: string) {\n return this.#availableDevices.filter((device) => device.kind === kind);\n }\n\n public getDeviceById(\n deviceId: string,\n kind: 'audioinput' | 'audiooutput' | 'videoinput'\n ) {\n const normalizedDeviceId = deviceId.toLowerCase();\n\n return this.#availableDevices.find((device) => {\n if (device.kind !== kind) return false;\n\n const deviceIdLower = device.deviceId.toLowerCase();\n\n // Exact match first\n if (device.deviceId === deviceId) return true;\n\n // iOS special cases\n if (\n normalizedDeviceId === 'speaker' &&\n deviceIdLower.includes('speaker')\n ) {\n return true;\n }\n if (\n normalizedDeviceId === 'bluetooth' &&\n deviceIdLower.includes('bluetooth')\n ) {\n return true;\n }\n if (\n normalizedDeviceId === 'earpiece' &&\n deviceIdLower.includes('earpiece')\n ) {\n return true;\n }\n\n return false;\n });\n }\n\n /**\n * Returns all audio input devices (microphone devices).\n */\n public getAudioDevices() {\n return this.getAvailableDevicesByKind('audioinput');\n }\n\n /**\n * Returns all video input devices.\n */\n public getVideoDevices() {\n return this.getAvailableDevicesByKind('videoinput');\n }\n\n /**\n * Returns all audio output devices (speaker devices).\n */\n public getSpeakerDevices() {\n const speakerDevices = this.#availableDevices;\n // In Mobile, speaker devices are the same as audio input devices\n return speakerDevices\n .filter((device) => device.kind === 'audioinput')\n .map((device) => ({\n ...device,\n deviceId: device.deviceId,\n label: device.label,\n kind: 'audiooutput',\n }));\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -14,10 +14,9 @@ class InCallManager {
14
14
  }
15
15
  start(setup) {
16
16
  setup = setup === undefined ? {} : setup;
17
- const auto = setup.auto !== false;
18
17
  const media = setup.media === 'video' ? 'video' : 'audio';
19
- const ringback = setup.ringback ? typeof setup.ringback === 'string' ? setup.ringback : '' : '';
20
- _InCallManager.start(media, auto, ringback);
18
+ _InCallManager.start();
19
+ if (media === 'audio') _InCallManager.setVoiceCallMode();
21
20
  }
22
21
  stop(setup) {
23
22
  setup = setup === undefined ? {} : setup;
@@ -67,6 +66,11 @@ class InCallManager {
67
66
  return await _InCallManager.abandonAudioFocusJS();
68
67
  }
69
68
  }
69
+ forceUpdateAudioDevices() {
70
+ if (_reactNative.Platform.OS === 'ios') {
71
+ _InCallManager.forceUpdateAudioDevices();
72
+ }
73
+ }
70
74
  }
71
75
  var _default = exports.default = new InCallManager();
72
76
  //# sourceMappingURL=NativeAudioManager.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["_reactNative","require","_InCallManager","NativeModules","InCallManager","constructor","vibrate","start","setup","undefined","auto","media","ringback","stop","busytone","getIsWiredHeadsetPluggedIn","e","isBluetoothHeadsetConnected","setKeepScreenOn","enable","setSpeakerphoneOn","setForceSpeakerphoneOn","_flag","flag","setMicrophoneMute","chooseAudioRoute","route","requestAudioFocus","Platform","OS","requestAudioFocusJS","abandonAudioFocus","abandonAudioFocusJS","_default","exports","default"],"sources":["NativeAudioManager.ts"],"sourcesContent":["// @ts-nocheck\nimport { Platform, NativeModules } from 'react-native';\n\nconst _InCallManager = NativeModules.InCallManager;\n\nclass InCallManager {\n constructor() {\n this.vibrate = false;\n }\n\n start(setup) {\n setup = setup === undefined ? {} : setup;\n const auto = setup.auto !== false;\n const media = setup.media === 'video' ? 'video' : 'audio';\n const ringback = setup.ringback\n ? typeof setup.ringback === 'string'\n ? setup.ringback\n : ''\n : '';\n _InCallManager.start(media, auto, ringback);\n }\n\n stop(setup) {\n setup = setup === undefined ? {} : setup;\n const busytone = setup.busytone\n ? typeof setup.busytone === 'string'\n ? setup.busytone\n : ''\n : '';\n _InCallManager.stop(busytone);\n }\n\n async getIsWiredHeadsetPluggedIn() {\n try {\n return await _InCallManager.getIsWiredHeadsetPluggedIn();\n } catch (e) {\n return {};\n }\n }\n\n async isBluetoothHeadsetConnected() {\n try {\n return await _InCallManager.isBluetoothHeadsetConnected();\n } catch (e) {\n return {};\n }\n }\n\n setKeepScreenOn(enable) {\n enable = enable === true;\n _InCallManager.setKeepScreenOn(enable);\n }\n\n setSpeakerphoneOn(enable) {\n enable = enable === true;\n _InCallManager.setSpeakerphoneOn(enable);\n }\n\n setForceSpeakerphoneOn(_flag) {\n const flag = typeof _flag === 'boolean' ? (_flag ? 1 : -1) : 0;\n _InCallManager.setForceSpeakerphoneOn(flag);\n }\n\n setMicrophoneMute(enable) {\n enable = enable === true;\n _InCallManager.setMicrophoneMute(enable);\n }\n\n async chooseAudioRoute(route: String) {\n return await _InCallManager.chooseAudioRoute(route);\n }\n\n async requestAudioFocus() {\n if (Platform.OS === 'android') {\n return await _InCallManager.requestAudioFocusJS();\n }\n }\n\n async abandonAudioFocus() {\n if (Platform.OS === 'android') {\n return await _InCallManager.abandonAudioFocusJS();\n }\n }\n}\n\nexport default new InCallManager();\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_reactNative","require","_InCallManager","NativeModules","InCallManager","constructor","vibrate","start","setup","undefined","media","setVoiceCallMode","stop","busytone","getIsWiredHeadsetPluggedIn","e","isBluetoothHeadsetConnected","setKeepScreenOn","enable","setSpeakerphoneOn","setForceSpeakerphoneOn","_flag","flag","setMicrophoneMute","chooseAudioRoute","route","requestAudioFocus","Platform","OS","requestAudioFocusJS","abandonAudioFocus","abandonAudioFocusJS","forceUpdateAudioDevices","_default","exports","default"],"sources":["NativeAudioManager.ts"],"sourcesContent":["// @ts-nocheck\nimport { Platform, NativeModules } from 'react-native';\n\nconst _InCallManager = NativeModules.InCallManager;\n\nclass InCallManager {\n constructor() {\n this.vibrate = false;\n }\n\n start(setup) {\n setup = setup === undefined ? {} : setup;\n const media = setup.media === 'video' ? 'video' : 'audio';\n _InCallManager.start();\n if (media === 'audio') _InCallManager.setVoiceCallMode();\n }\n\n stop(setup) {\n setup = setup === undefined ? {} : setup;\n const busytone = setup.busytone\n ? typeof setup.busytone === 'string'\n ? setup.busytone\n : ''\n : '';\n _InCallManager.stop(busytone);\n }\n\n async getIsWiredHeadsetPluggedIn() {\n try {\n return await _InCallManager.getIsWiredHeadsetPluggedIn();\n } catch (e) {\n return {};\n }\n }\n\n async isBluetoothHeadsetConnected() {\n try {\n return await _InCallManager.isBluetoothHeadsetConnected();\n } catch (e) {\n return {};\n }\n }\n\n setKeepScreenOn(enable) {\n enable = enable === true;\n _InCallManager.setKeepScreenOn(enable);\n }\n\n setSpeakerphoneOn(enable) {\n enable = enable === true;\n _InCallManager.setSpeakerphoneOn(enable);\n }\n\n setForceSpeakerphoneOn(_flag) {\n const flag = typeof _flag === 'boolean' ? (_flag ? 1 : -1) : 0;\n _InCallManager.setForceSpeakerphoneOn(flag);\n }\n\n setMicrophoneMute(enable) {\n enable = enable === true;\n _InCallManager.setMicrophoneMute(enable);\n }\n\n async chooseAudioRoute(route: String) {\n return await _InCallManager.chooseAudioRoute(route);\n }\n\n async requestAudioFocus() {\n if (Platform.OS === 'android') {\n return await _InCallManager.requestAudioFocusJS();\n }\n }\n\n async abandonAudioFocus() {\n if (Platform.OS === 'android') {\n return await _InCallManager.abandonAudioFocusJS();\n }\n }\n\n forceUpdateAudioDevices() {\n if (Platform.OS === 'ios') {\n _InCallManager.forceUpdateAudioDevices();\n }\n }\n}\n\nexport default new InCallManager();\n"],"mappings":";;;;;;AACA,IAAAA,YAAA,GAAAC,OAAA;AADA;;AAGA,MAAMC,cAAc,GAAGC,0BAAa,CAACC,aAAa;AAElD,MAAMA,aAAa,CAAC;EAClBC,WAAWA,CAAA,EAAG;IACZ,IAAI,CAACC,OAAO,GAAG,KAAK;EACtB;EAEAC,KAAKA,CAACC,KAAK,EAAE;IACXA,KAAK,GAAGA,KAAK,KAAKC,SAAS,GAAG,CAAC,CAAC,GAAGD,KAAK;IACxC,MAAME,KAAK,GAAGF,KAAK,CAACE,KAAK,KAAK,OAAO,GAAG,OAAO,GAAG,OAAO;IACzDR,cAAc,CAACK,KAAK,CAAC,CAAC;IACtB,IAAIG,KAAK,KAAK,OAAO,EAAER,cAAc,CAACS,gBAAgB,CAAC,CAAC;EAC1D;EAEAC,IAAIA,CAACJ,KAAK,EAAE;IACVA,KAAK,GAAGA,KAAK,KAAKC,SAAS,GAAG,CAAC,CAAC,GAAGD,KAAK;IACxC,MAAMK,QAAQ,GAAGL,KAAK,CAACK,QAAQ,GAC3B,OAAOL,KAAK,CAACK,QAAQ,KAAK,QAAQ,GAChCL,KAAK,CAACK,QAAQ,GACd,EAAE,GACJ,EAAE;IACNX,cAAc,CAACU,IAAI,CAACC,QAAQ,CAAC;EAC/B;EAEA,MAAMC,0BAA0BA,CAAA,EAAG;IACjC,IAAI;MACF,OAAO,MAAMZ,cAAc,CAACY,0BAA0B,CAAC,CAAC;IAC1D,CAAC,CAAC,OAAOC,CAAC,EAAE;MACV,OAAO,CAAC,CAAC;IACX;EACF;EAEA,MAAMC,2BAA2BA,CAAA,EAAG;IAClC,IAAI;MACF,OAAO,MAAMd,cAAc,CAACc,2BAA2B,CAAC,CAAC;IAC3D,CAAC,CAAC,OAAOD,CAAC,EAAE;MACV,OAAO,CAAC,CAAC;IACX;EACF;EAEAE,eAAeA,CAACC,MAAM,EAAE;IACtBA,MAAM,GAAGA,MAAM,KAAK,IAAI;IACxBhB,cAAc,CAACe,eAAe,CAACC,MAAM,CAAC;EACxC;EAEAC,iBAAiBA,CAACD,MAAM,EAAE;IACxBA,MAAM,GAAGA,MAAM,KAAK,IAAI;IACxBhB,cAAc,CAACiB,iBAAiB,CAACD,MAAM,CAAC;EAC1C;EAEAE,sBAAsBA,CAACC,KAAK,EAAE;IAC5B,MAAMC,IAAI,GAAG,OAAOD,KAAK,KAAK,SAAS,GAAIA,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC,GAAI,CAAC;IAC9DnB,cAAc,CAACkB,sBAAsB,CAACE,IAAI,CAAC;EAC7C;EAEAC,iBAAiBA,CAACL,MAAM,EAAE;IACxBA,MAAM,GAAGA,MAAM,KAAK,IAAI;IACxBhB,cAAc,CAACqB,iBAAiB,CAACL,MAAM,CAAC;EAC1C;EAEA,MAAMM,gBAAgBA,CAACC,KAAa,EAAE;IACpC,OAAO,MAAMvB,cAAc,CAACsB,gBAAgB,CAACC,KAAK,CAAC;EACrD;EAEA,MAAMC,iBAAiBA,CAAA,EAAG;IACxB,IAAIC,qBAAQ,CAACC,EAAE,KAAK,SAAS,EAAE;MAC7B,OAAO,MAAM1B,cAAc,CAAC2B,mBAAmB,CAAC,CAAC;IACnD;EACF;EAEA,MAAMC,iBAAiBA,CAAA,EAAG;IACxB,IAAIH,qBAAQ,CAACC,EAAE,KAAK,SAAS,EAAE;MAC7B,OAAO,MAAM1B,cAAc,CAAC6B,mBAAmB,CAAC,CAAC;IACnD;EACF;EAEAC,uBAAuBA,CAAA,EAAG;IACxB,IAAIL,qBAAQ,CAACC,EAAE,KAAK,KAAK,EAAE;MACzB1B,cAAc,CAAC8B,uBAAuB,CAAC,CAAC;IAC1C;EACF;AACF;AAAC,IAAAC,QAAA,GAAAC,OAAA,CAAAC,OAAA,GAEc,IAAI/B,aAAa,CAAC,CAAC","ignoreList":[]}
@@ -4,5 +4,5 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.SDK_VERSION = void 0;
7
- const SDK_VERSION = exports.SDK_VERSION = '0.2.1';
7
+ const SDK_VERSION = exports.SDK_VERSION = '0.2.2-staging.2';
8
8
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["SDK_VERSION","exports"],"sources":["version.ts"],"sourcesContent":["export const SDK_VERSION = '0.2.1';\n"],"mappings":";;;;;;AAAO,MAAMA,WAAW,GAAAC,OAAA,CAAAD,WAAA,GAAG,OAAO","ignoreList":[]}
1
+ {"version":3,"names":["SDK_VERSION","exports"],"sources":["version.ts"],"sourcesContent":["export const SDK_VERSION = '0.2.2-staging.2';\n"],"mappings":";;;;;;AAAO,MAAMA,WAAW,GAAAC,OAAA,CAAAD,WAAA,GAAG,iBAAiB","ignoreList":[]}
@@ -39,6 +39,7 @@ var _localMediaUtils = /*#__PURE__*/new WeakMap();
39
39
  var _appState = /*#__PURE__*/new WeakMap();
40
40
  var _appStateSubscription = /*#__PURE__*/new WeakMap();
41
41
  var _interval = /*#__PURE__*/new WeakMap();
42
+ var _deviceRemovalTimeout = /*#__PURE__*/new WeakMap();
42
43
  export default class LocalMediaHandler extends EventEmitter {
43
44
  async configureForeground() {
44
45
  if (Platform.OS !== 'android') return;
@@ -77,6 +78,7 @@ export default class LocalMediaHandler extends EventEmitter {
77
78
  _defineProperty(this, "_pendingScreenShare", false);
78
79
  _defineProperty(this, "currentDevices", void 0);
79
80
  _defineProperty(this, "permissions", void 0);
81
+ _classPrivateFieldInitSpec(this, _deviceRemovalTimeout, null);
80
82
  _defineProperty(this, "_handleAppStateChange", nextAppState => {
81
83
  if (_classPrivateFieldGet(_appState, this).match(/inactive|background/) && nextAppState === 'active') {
82
84
  BackgroundTimer.clearInterval(_classPrivateFieldGet(_interval, this));
@@ -129,13 +131,14 @@ export default class LocalMediaHandler extends EventEmitter {
129
131
  this.oniOSBroadcastStop();
130
132
  });
131
133
  }
132
- InCallManger.start({});
134
+ InCallManger.start({
135
+ media: 'video'
136
+ });
133
137
  }
134
138
  async conditionallyRestartAudio() {
135
139
  if (!this.currentDevices.audio || !this.audioEnabled) {
136
140
  return;
137
141
  }
138
- // log.info('maybe_restart_audio: ');
139
142
  await Promise.race([new Promise(resolve => {
140
143
  var _this$audioTrack;
141
144
  return (_this$audioTrack = this.audioTrack) === null || _this$audioTrack === void 0 ? void 0 : _this$audioTrack.addEventListener('unmute', e => {
@@ -153,8 +156,6 @@ export default class LocalMediaHandler extends EventEmitter {
153
156
  }
154
157
  async conditionallyRestartVideo() {
155
158
  if (!this.currentDevices.video || !this.videoEnabled) return;
156
- // log.info('maybe_restart_video');
157
-
158
159
  await Promise.race([new Promise(resolve => {
159
160
  var _this$videoTrack;
160
161
  return (_this$videoTrack = this.videoTrack) === null || _this$videoTrack === void 0 ? void 0 : _this$videoTrack.addEventListener('unmute', resolve);
@@ -249,6 +250,10 @@ export default class LocalMediaHandler extends EventEmitter {
249
250
  if (this.audioTrack && this.permissions.audio === 'NOT_REQUESTED') {
250
251
  await _classPrivateFieldGet(_localMediaUtils, this).repopulateAvailableDevices();
251
252
  }
253
+
254
+ // Force update audio devices on iOS after audio session is active
255
+ // This ensures route change notifications start firing
256
+ InCallManger.forceUpdateAudioDevices();
252
257
  this.emit('DEVICE_CHANGE', {
253
258
  device: this.currentDevices.audio
254
259
  });
@@ -307,14 +312,33 @@ export default class LocalMediaHandler extends EventEmitter {
307
312
  });
308
313
  }
309
314
  async setupSpeaker(deviceId) {
310
- var _this$currentDevices$4;
315
+ var _this$currentDevices$5;
311
316
  const speakerDevices = _classPrivateFieldGet(_localMediaUtils, this).getSpeakerDevices();
312
317
  if (!speakerDevices.length) {
313
318
  return;
314
319
  }
315
- const lastDeviceIndex = speakerDevices.length - 1;
316
- const speakerDeviceId = deviceId ?? speakerDevices[lastDeviceIndex].deviceId;
317
- if (((_this$currentDevices$4 = this.currentDevices.speaker) === null || _this$currentDevices$4 === void 0 ? void 0 : _this$currentDevices$4.deviceId) !== speakerDeviceId) {
320
+ let speakerDeviceId;
321
+ if (deviceId) {
322
+ // If explicit deviceId provided, use it
323
+ speakerDeviceId = deviceId;
324
+ } else {
325
+ // Prefer current device if it's still available
326
+ const currentDeviceStillAvailable = speakerDevices.find(d => {
327
+ var _this$currentDevices$4;
328
+ return d.deviceId === ((_this$currentDevices$4 = this.currentDevices.speaker) === null || _this$currentDevices$4 === void 0 ? void 0 : _this$currentDevices$4.deviceId);
329
+ });
330
+ if (currentDeviceStillAvailable) {
331
+ // Keep current device if it's still connected
332
+ speakerDeviceId = this.currentDevices.speaker.deviceId;
333
+ } else {
334
+ // Otherwise, prefer Bluetooth > Wired > Speaker > Earpiece
335
+ const bluetoothDevice = speakerDevices.find(d => d.deviceId === 'bluetooth');
336
+ const wiredDevice = speakerDevices.find(d => d.deviceId === 'wired');
337
+ const speakerDevice = speakerDevices.find(d => d.deviceId === 'speaker');
338
+ speakerDeviceId = (bluetoothDevice === null || bluetoothDevice === void 0 ? void 0 : bluetoothDevice.deviceId) ?? (wiredDevice === null || wiredDevice === void 0 ? void 0 : wiredDevice.deviceId) ?? (speakerDevice === null || speakerDevice === void 0 ? void 0 : speakerDevice.deviceId) ?? speakerDevices[0].deviceId;
339
+ }
340
+ }
341
+ if (((_this$currentDevices$5 = this.currentDevices.speaker) === null || _this$currentDevices$5 === void 0 ? void 0 : _this$currentDevices$5.deviceId) !== speakerDeviceId) {
318
342
  // Audio Input devices are same as output devices in mobile
319
343
  this.currentDevices.audio = _classPrivateFieldGet(_localMediaUtils, this).getDeviceById(speakerDeviceId, 'audioinput');
320
344
  this.currentDevices.speaker = this.currentDevices.audio;
@@ -504,7 +528,6 @@ export default class LocalMediaHandler extends EventEmitter {
504
528
  audio,
505
529
  video
506
530
  } = tracks;
507
- // console.log('SetScreenshare called');
508
531
  if (!audio || !video) {
509
532
  this.stopScreenShareTracks({
510
533
  audio: !!audio,
@@ -553,8 +576,8 @@ export default class LocalMediaHandler extends EventEmitter {
553
576
  * if the audio track is not preset or it has ended
554
577
  */
555
578
  if (!this.audioTrack || this.audioTrack.readyState === 'ended') {
556
- var _this$currentDevices$5;
557
- await this.setupAudioStream((_this$currentDevices$5 = this.currentDevices.audio) === null || _this$currentDevices$5 === void 0 ? void 0 : _this$currentDevices$5.deviceId);
579
+ var _this$currentDevices$6;
580
+ await this.setupAudioStream((_this$currentDevices$6 = this.currentDevices.audio) === null || _this$currentDevices$6 === void 0 ? void 0 : _this$currentDevices$6.deviceId);
558
581
  }
559
582
  // if we still can't get a track after setting up audio stream
560
583
  // do not toggle the audio state
@@ -579,7 +602,7 @@ export default class LocalMediaHandler extends EventEmitter {
579
602
  await this.toggleVideo();
580
603
  }
581
604
  async toggleVideo() {
582
- var _this$currentDevices$6;
605
+ var _this$currentDevices$7;
583
606
  if (this.permissions.video !== 'ACCEPTED') {
584
607
  try {
585
608
  const permResult = await setupPermissions(false, true);
@@ -606,7 +629,7 @@ export default class LocalMediaHandler extends EventEmitter {
606
629
  * hence it must be set to true first.
607
630
  */
608
631
  this.videoEnabled = true;
609
- await this.setupVideoStream((_this$currentDevices$6 = this.currentDevices.video) === null || _this$currentDevices$6 === void 0 ? void 0 : _this$currentDevices$6.deviceId);
632
+ await this.setupVideoStream((_this$currentDevices$7 = this.currentDevices.video) === null || _this$currentDevices$7 === void 0 ? void 0 : _this$currentDevices$7.deviceId);
610
633
  }
611
634
  async setAudioDevice(device) {
612
635
  await this.setupAudioStream(device.deviceId);
@@ -704,12 +727,26 @@ export default class LocalMediaHandler extends EventEmitter {
704
727
  if (changedDevices.added.length) [addedDevice] = changedDevices.added;
705
728
  if (changedDevices.removed.length) [removedDevice] = changedDevices.removed;
706
729
 
730
+ // Update currentDevices.speaker when platform reports selected device change
731
+ if (changedDevices.selectedDevice) {
732
+ const selectedDeviceInfo = _classPrivateFieldGet(_localMediaUtils, this).getDeviceById(changedDevices.selectedDevice, 'audioinput');
733
+ if (selectedDeviceInfo) {
734
+ this.currentDevices.speaker = selectedDeviceInfo;
735
+ this.currentDevices.audio = selectedDeviceInfo;
736
+ }
737
+ }
738
+
707
739
  /**
708
740
  * NOTE(roerohan): forceStopTrack is set required to be set to true for firefox.
709
741
  * https://stackoverflow.com/questions/59068146/navigator-mediadevices-getusermedia-api-rejecting-with-error-notreadableerror
710
742
  * forceStopTrack is the second argument of setupAudioStream and setupVideoStream.
711
743
  */
712
744
  if (addedDevice) {
745
+ // Clear any pending device removal timeout when a device is added
746
+ if (_classPrivateFieldGet(_deviceRemovalTimeout, this)) {
747
+ clearTimeout(_classPrivateFieldGet(_deviceRemovalTimeout, this));
748
+ _classPrivateFieldSet(_deviceRemovalTimeout, this, null);
749
+ }
713
750
  if (addedDevice.kind === 'audioinput') {
714
751
  if (this.permissions.audio === 'DENIED' || this.permissions.audio === 'NOT_REQUESTED') {
715
752
  await this.setupSpeaker(addedDevice.deviceId);
@@ -723,21 +760,42 @@ export default class LocalMediaHandler extends EventEmitter {
723
760
  }
724
761
  this.emit('AUDIO_TRACK_CHANGE');
725
762
  }
726
- if (removedDevice) {
727
- if (removedDevice.kind === 'audioinput') {
728
- if (this.permissions.audio === 'DENIED' || this.permissions.audio === 'NOT_REQUESTED') {
763
+
764
+ // Only handle device removal if no device was added
765
+ // This prevents switching away from newly connected devices (e.g., Bluetooth)
766
+ if (removedDevice && !addedDevice) {
767
+ // For Bluetooth devices, add a delay to handle rapid reconnections
768
+ // (e.g., when AirPods are put in ears, they briefly disconnect then reconnect)
769
+ const isBluetoothRemoved = removedDevice.deviceId === 'bluetooth';
770
+ const handleRemoval = async () => {
771
+ if (removedDevice.kind === 'audioinput') {
772
+ if (this.permissions.audio === 'DENIED' || this.permissions.audio === 'NOT_REQUESTED') {
773
+ await this.setupSpeaker();
774
+ } else {
775
+ await this.setupAudioStream();
776
+ }
777
+ } else if (removedDevice.kind === 'videoinput') {
778
+ await this.setupVideoStream();
779
+ } else if (removedDevice.kind === 'audiooutput') {
729
780
  await this.setupSpeaker();
730
- } else {
731
- await this.setupAudioStream();
732
781
  }
733
- } else if (removedDevice.kind === 'videoinput') {
734
- await this.setupVideoStream();
735
- } else if (removedDevice.kind === 'audiooutput') {
736
- await this.setupSpeaker();
782
+ this.emit('AUDIO_TRACK_CHANGE');
783
+ };
784
+ if (isBluetoothRemoved) {
785
+ // Wait 500ms before switching away from Bluetooth to allow for reconnection
786
+ _classPrivateFieldSet(_deviceRemovalTimeout, this, setTimeout(handleRemoval, 500));
787
+ } else {
788
+ // For other devices, handle removal immediately
789
+ await handleRemoval();
737
790
  }
738
- this.emit('AUDIO_TRACK_CHANGE');
739
791
  }
740
- if (changedDevices.added.length || changedDevices.removed.length) {
792
+
793
+ // Emit DEVICE_LIST_UPDATED if:
794
+ // 1. Devices were added or removed, OR
795
+ // 2. Selected device changed (platform routed to a different device)
796
+ const hasDeviceListChanged = changedDevices.added.length || changedDevices.removed.length;
797
+ const hasSelectedDeviceInfo = changedDevices.selectedDevice !== undefined;
798
+ if (hasDeviceListChanged || hasSelectedDeviceInfo) {
741
799
  this.emit('DEVICE_LIST_UPDATED', changedDevices);
742
800
  }
743
801
  }