{"version":3,"sources":["../../../../src/sensors/useDevicesList/core.ts"],"sourcesContent":["import {\n  createSupported,\n  onMount,\n  observable,\n  type DeepMaybeObservable,\n  type ReadonlyObservable,\n  type Supportable,\n} from \"@usels/core\";\nimport { defaultNavigator } from \"@shared/configurable\";\nimport { createEventListener } from \"../../browser/useEventListener/core\";\n\nexport interface UseDevicesListOptions {\n  /** Request permissions on mount */\n  requestPermissions?: boolean;\n  /** Constraints for getUserMedia when requesting permissions */\n  constraints?: MediaStreamConstraints;\n  /** Callback when device list is updated */\n  onUpdated?: (devices: MediaDeviceInfo[]) => void;\n}\n\nexport interface UseDevicesListReturn extends Supportable {\n  /** All enumerated media devices */\n  devices$: ReadonlyObservable<MediaDeviceInfo[]>;\n  /** Video input devices (cameras) */\n  videoInputs$: ReadonlyObservable<MediaDeviceInfo[]>;\n  /** Audio input devices (microphones) */\n  audioInputs$: ReadonlyObservable<MediaDeviceInfo[]>;\n  /** Audio output devices (speakers) */\n  audioOutputs$: ReadonlyObservable<MediaDeviceInfo[]>;\n  /** Whether media permissions have been granted */\n  permissionGranted$: ReadonlyObservable<boolean>;\n  /** Request media device permissions */\n  ensurePermissions: () => Promise<boolean>;\n}\n\n/**\n * Framework-agnostic reactive wrapper around\n * [MediaDevices.enumerateDevices()](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/enumerateDevices).\n *\n * Lists available media input/output devices and tracks changes via the\n * `devicechange` event on `navigator.mediaDevices`. Optionally requests\n * permissions on mount.\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function createDevicesList(\n  options?: DeepMaybeObservable<UseDevicesListOptions>\n): UseDevicesListReturn {\n  const opts$ = observable(options);\n\n  const isSupported$ = createSupported(\n    () =>\n      !!defaultNavigator &&\n      \"mediaDevices\" in defaultNavigator &&\n      !!defaultNavigator.mediaDevices?.enumerateDevices\n  );\n\n  const devices$ = observable<MediaDeviceInfo[]>([]);\n  const permissionGranted$ = observable(false);\n\n  const videoInputs$ = observable(() => devices$.get().filter((d) => d.kind === \"videoinput\"));\n  const audioInputs$ = observable(() => devices$.get().filter((d) => d.kind === \"audioinput\"));\n  const audioOutputs$ = observable(() => devices$.get().filter((d) => d.kind === \"audiooutput\"));\n\n  const update = async () => {\n    if (!defaultNavigator?.mediaDevices?.enumerateDevices) return;\n    const deviceList = await defaultNavigator.mediaDevices.enumerateDevices();\n    devices$.set(deviceList);\n    opts$.peek()?.onUpdated?.(deviceList);\n  };\n\n  const ensurePermissions = async (): Promise<boolean> => {\n    if (!isSupported$.peek()) return false;\n    if (permissionGranted$.peek()) return true;\n\n    try {\n      const constraints = opts$.peek()?.constraints ?? { audio: true, video: true };\n      const stream = await defaultNavigator!.mediaDevices.getUserMedia(constraints);\n      stream.getTracks().forEach((t) => t.stop());\n      permissionGranted$.set(true);\n      await update();\n      return true;\n    } catch {\n      return false;\n    }\n  };\n\n  createEventListener(defaultNavigator?.mediaDevices as EventTarget, \"devicechange\", () => {\n    update();\n  });\n\n  onMount(() => {\n    if (!isSupported$.peek()) return;\n\n    const requestPermissions = opts$.peek()?.requestPermissions ?? false;\n    if (requestPermissions) {\n      ensurePermissions();\n    } else {\n      update();\n    }\n  });\n\n  return {\n    isSupported$,\n    devices$: devices$ as ReadonlyObservable<MediaDeviceInfo[]>,\n    videoInputs$: videoInputs$ as ReadonlyObservable<MediaDeviceInfo[]>,\n    audioInputs$: audioInputs$ as ReadonlyObservable<MediaDeviceInfo[]>,\n    audioOutputs$: audioOutputs$ as ReadonlyObservable<MediaDeviceInfo[]>,\n    permissionGranted$: permissionGranted$ as ReadonlyObservable<boolean>,\n    ensurePermissions,\n  };\n}\n"],"mappings":"AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AACP,SAAS,wBAAwB;AACjC,SAAS,2BAA2B;AAAA;AAmC7B,SAAS,kBACd,SACsB;AACtB,QAAM,QAAQ,WAAW,OAAO;AAEhC,QAAM,eAAe;AAAA,IACnB,MACE,CAAC,CAAC,oBACF,kBAAkB,oBAClB,CAAC,CAAC,iBAAiB,cAAc;AAAA,EACrC;AAEA,QAAM,WAAW,WAA8B,CAAC,CAAC;AACjD,QAAM,qBAAqB,WAAW,KAAK;AAE3C,QAAM,eAAe,WAAW,MAAM,SAAS,IAAI,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,YAAY,CAAC;AAC3F,QAAM,eAAe,WAAW,MAAM,SAAS,IAAI,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,YAAY,CAAC;AAC3F,QAAM,gBAAgB,WAAW,MAAM,SAAS,IAAI,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,aAAa,CAAC;AAE7F,QAAM,SAAS,YAAY;AACzB,QAAI,CAAC,kBAAkB,cAAc,iBAAkB;AACvD,UAAM,aAAa,MAAM,iBAAiB,aAAa,iBAAiB;AACxE,aAAS,IAAI,UAAU;AACvB,UAAM,KAAK,GAAG,YAAY,UAAU;AAAA,EACtC;AAEA,QAAM,oBAAoB,YAA8B;AACtD,QAAI,CAAC,aAAa,KAAK,EAAG,QAAO;AACjC,QAAI,mBAAmB,KAAK,EAAG,QAAO;AAEtC,QAAI;AACF,YAAM,cAAc,MAAM,KAAK,GAAG,eAAe,EAAE,OAAO,MAAM,OAAO,KAAK;AAC5E,YAAM,SAAS,MAAM,iBAAkB,aAAa,aAAa,WAAW;AAC5E,aAAO,UAAU,EAAE,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC;AAC1C,yBAAmB,IAAI,IAAI;AAC3B,YAAM,OAAO;AACb,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAEA,sBAAoB,kBAAkB,cAA6B,gBAAgB,MAAM;AACvF,WAAO;AAAA,EACT,CAAC;AAED,UAAQ,MAAM;AACZ,QAAI,CAAC,aAAa,KAAK,EAAG;AAE1B,UAAM,qBAAqB,MAAM,KAAK,GAAG,sBAAsB;AAC/D,QAAI,oBAAoB;AACtB,wBAAkB;AAAA,IACpB,OAAO;AACL,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AAED,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":[]}