| <script lang="ts"> | |
| import type { HTMLAudioAttributes } from "svelte/elements"; | |
| import { createEventDispatcher } from "svelte"; | |
| interface Props extends HTMLAudioAttributes { | |
| "data-testid"?: string; | |
| } | |
| type $$Props = Props; | |
| import { resolve_wasm_src } from "@gradio/wasm/svelte"; | |
| export let src: HTMLAudioAttributes["src"] = undefined; | |
| let resolved_src: typeof src; | |
| // The `src` prop can be updated before the Promise from `resolve_wasm_src` is resolved. | |
| // In such a case, the resolved value for the old `src` has to be discarded, | |
| // This variable `latest_src` is used to pick up only the value resolved for the latest `src` prop. | |
| let latest_src: typeof src; | |
| $: { | |
| // In normal (non-Wasm) Gradio, the `<audio>` element should be rendered with the passed `src` props immediately | |
| // without waiting for `resolve_wasm_src()` to resolve. | |
| // If it waits, a black image is displayed until the async task finishes | |
| // and it leads to undesirable flickering. | |
| // So set `src` to `resolved_src` here. | |
| resolved_src = src; | |
| latest_src = src; | |
| const resolving_src = src; | |
| resolve_wasm_src(resolving_src).then((s) => { | |
| if (latest_src === resolving_src) { | |
| resolved_src = s; | |
| } | |
| }); | |
| } | |
| const dispatch = createEventDispatcher(); | |
| </script> | |
| <audio | |
| src={resolved_src} | |
| {...$$restProps} | |
| on:play={dispatch.bind(null, "play")} | |
| on:pause={dispatch.bind(null, "pause")} | |
| on:ended={dispatch.bind(null, "ended")} | |
| /> | |