{"version":3,"sources":["../src/hooks/use-select-input-device-agent.ts","../src/hooks/use-observable-state.ts"],"sourcesContent":["/*\n *  Copyright (c) 2024. Rapida\n *\n *  Permission is hereby granted, free of charge, to any person obtaining a copy\n *  of this software and associated documentation files (the \"Software\"), to deal\n *  in the Software without restriction, including without limitation the rights\n *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n *  copies of the Software, and to permit persons to whom the Software is\n *  furnished to do so, subject to the following conditions:\n *\n *  The above copyright notice and this permission notice shall be included in\n *  all copies or substantial portions of the Software.\n *\n *  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n *  THE SOFTWARE.\n *\n *  Author: Prashant <prashant@rapida.ai>\n *\n */\nimport * as React from \"react\";\nimport { useObservableState } from \"@/rapida/hooks/use-observable-state\";\nimport { BehaviorSubject } from \"rxjs\";\nimport {\n  browserMediaDeviceObserver,\n  agentInputMediaDeviceChangeObservable,\n} from \"@/rapida/hooks/observables/voice-agent\";\nimport { useMaybeVoiceAgent } from \"@/rapida/hooks/use-voice-agent\";\nimport { VoiceAgent } from \"@/rapida/agents/voice-agent\";\n\n/** @public */\ninterface UseMediaDeviceSelectProps {\n  /**\n   * this will call getUserMedia if the permissions are not yet given to enumerate the devices with device labels.\n   * in some browsers multiple calls to getUserMedia result in multiple permission prompts.\n   * It's generally advised only flip this to true, once a (preview) track has been acquired successfully with the\n   * appropriate permissions.\n   *\n   * @see {@link MediaDeviceMenu}\n   * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/enumerateDevices | MDN enumerateDevices}\n   */\n  requestPermissions?: boolean;\n  /**\n   * this callback gets called if an error is thrown when failing to select a device and also if a user\n   * denied permissions, eventhough the `requestPermissions` option is set to `true`.\n   * Most commonly this will emit a MediaDeviceError\n   */\n  onError?: (e: Error) => void;\n}\n\n/**\n * The `useMediaDeviceSelect` hook is used to implement the `MediaDeviceSelect` component and\n * returns o.a. the list of devices of a given kind (audioinput or videoinput), the currently active device\n * and a function to set the the active device.\n *\n * @example\n * ```tsx\n * const { devices, activeDeviceId, setActiveMediaDevice } = useMediaDeviceSelect({kind: 'audioinput'});\n * ```\n * @public\n */\nexport function useSelectInputDeviceAgent({\n  requestPermissions,\n  onError,\n}: UseMediaDeviceSelectProps) {\n  const voiceAgentContext = useMaybeVoiceAgent();\n  // List of all devices.\n  const deviceObserver = React.useMemo(\n    () => browserMediaDeviceObserver(\"audioinput\", onError, requestPermissions),\n    [requestPermissions, onError]\n  );\n  // @ts-ignore\n  const devices: MediaDeviceInfo[] = useObservableState(\n    deviceObserver,\n    [] as MediaDeviceInfo[]\n  );\n  //\n  const [currentDeviceId, setCurrentDeviceId] = React.useState<string>(\n    voiceAgentContext?.inputMediaDevice ?? \"\"\n  );\n  const { className, activeDeviceObservable, setActiveMediaDevice } =\n    React.useMemo(\n      () => setupDeviceSelector(\"audioinput\", voiceAgentContext),\n      [voiceAgentContext]\n    );\n\n  React.useEffect(() => {\n    const listener = activeDeviceObservable.subscribe((deviceId) => {\n      if (deviceId && deviceId !== currentDeviceId) {\n        setCurrentDeviceId(deviceId);\n      }\n    });\n    return () => {\n      listener?.unsubscribe();\n    };\n  }, [activeDeviceObservable]);\n\n  return {\n    devices,\n    className,\n    activeDeviceId: currentDeviceId,\n    setActiveMediaDevice,\n  };\n}\n\nfunction setupDeviceSelector(_: MediaDeviceKind, agent?: VoiceAgent) {\n  const activeDeviceSubject = new BehaviorSubject<string | undefined>(\n    undefined\n  );\n\n  const activeDeviceObservable = agent\n    ? agentInputMediaDeviceChangeObservable(agent)\n    : activeDeviceSubject.asObservable();\n\n  const setActiveMediaDevice = async (id: string) => {\n    if (agent) {\n      await agent.setInputMediaDevice(id);\n    } else if (activeDeviceSubject.value !== id) {\n      activeDeviceSubject.next(id);\n    }\n  };\n  const className: string = \"media-device-select\";\n  return {\n    className,\n    activeDeviceObservable,\n    setActiveMediaDevice,\n  };\n}\n","/*\n *  Copyright (c) 2024. Rapida\n *\n *  Permission is hereby granted, free of charge, to any person obtaining a copy\n *  of this software and associated documentation files (the \"Software\"), to deal\n *  in the Software without restriction, including without limitation the rights\n *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n *  copies of the Software, and to permit persons to whom the Software is\n *  furnished to do so, subject to the following conditions:\n *\n *  The above copyright notice and this permission notice shall be included in\n *  all copies or substantial portions of the Software.\n *\n *  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n *  THE SOFTWARE.\n *\n *  Author: Prashant <prashant@rapida.ai>\n *\n */\nimport * as React from \"react\";\n// @ts-ignore\nimport type { Observable } from \"rxjs\";\n\n/**\n * @internal\n */\nexport function useObservableState<T>(\n  observable: Observable<T> | undefined,\n  startWith: T,\n  resetWhenObservableChanges = true\n): T {\n  const [state, setState] = React.useState<T>(startWith);\n  React.useEffect(() => {\n    if (resetWhenObservableChanges) {\n      setState(startWith);\n    }\n    // observable state doesn't run in SSR\n    if (typeof window === \"undefined\" || !observable) return;\n    const subscription = observable.subscribe(setState);\n    //\n    return () => subscription.unsubscribe();\n  }, [observable, resetWhenObservableChanges]);\n  return state;\n}\n"],"mappings":";;;;;;;AAwBA,YAAYA,YAAW;;;ACAvB,YAAY,WAAW;AAOhB,SAAS,mBACd,YACA,WACA,6BAA6B,MAC1B;AACH,QAAM,CAAC,OAAO,QAAQ,IAAU,eAAY,SAAS;AACrD,EAAM,gBAAU,MAAM;AACpB,QAAI,4BAA4B;AAC9B,eAAS,SAAS;AAAA,IACpB;AAEA,QAAI,OAAO,WAAW,eAAe,CAAC,WAAY;AAClD,UAAM,eAAe,WAAW,UAAU,QAAQ;AAElD,WAAO,MAAM,aAAa,YAAY;AAAA,EACxC,GAAG,CAAC,YAAY,0BAA0B,CAAC;AAC3C,SAAO;AACT;;;ADtBA,SAAS,uBAAuB;AAuCzB,SAAS,0BAA0B;AAAA,EACxC;AAAA,EACA;AACF,GAA8B;AAC5B,QAAM,oBAAoB,mBAAmB;AAE7C,QAAM,iBAAuB;AAAA,IAC3B,MAAM,2BAA2B,cAAc,SAAS,kBAAkB;AAAA,IAC1E,CAAC,oBAAoB,OAAO;AAAA,EAC9B;AAEA,QAAM,UAA6B;AAAA,IACjC;AAAA,IACA,CAAC;AAAA,EACH;AAEA,QAAM,CAAC,iBAAiB,kBAAkB,IAAU;AAAA,IAClD,mBAAmB,oBAAoB;AAAA,EACzC;AACA,QAAM,EAAE,WAAW,wBAAwB,qBAAqB,IACxD;AAAA,IACJ,MAAM,oBAAoB,cAAc,iBAAiB;AAAA,IACzD,CAAC,iBAAiB;AAAA,EACpB;AAEF,EAAM,iBAAU,MAAM;AACpB,UAAM,WAAW,uBAAuB,UAAU,CAAC,aAAa;AAC9D,UAAI,YAAY,aAAa,iBAAiB;AAC5C,2BAAmB,QAAQ;AAAA,MAC7B;AAAA,IACF,CAAC;AACD,WAAO,MAAM;AACX,gBAAU,YAAY;AAAA,IACxB;AAAA,EACF,GAAG,CAAC,sBAAsB,CAAC;AAE3B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,gBAAgB;AAAA,IAChB;AAAA,EACF;AACF;AAEA,SAAS,oBAAoB,GAAoB,OAAoB;AACnE,QAAM,sBAAsB,IAAI;AAAA,IAC9B;AAAA,EACF;AAEA,QAAM,yBAAyB,QAC3B,sCAAsC,KAAK,IAC3C,oBAAoB,aAAa;AAErC,QAAM,uBAAuB,OAAO,OAAe;AACjD,QAAI,OAAO;AACT,YAAM,MAAM,oBAAoB,EAAE;AAAA,IACpC,WAAW,oBAAoB,UAAU,IAAI;AAC3C,0BAAoB,KAAK,EAAE;AAAA,IAC7B;AAAA,EACF;AACA,QAAM,YAAoB;AAC1B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":["React"]}