///|
extern "js" fn create_audio_object_url(bytes : Bytes, mime : String) -> String =
#| (bytes, mime) => {
#| return URL.createObjectURL(new Blob([bytes], { type: mime }));
#| }
///|
extern "js" fn revoke_object_url(url : String) -> Unit =
#| (url) => {
#| if (typeof url === 'string' && url.startsWith('blob:')) {
#| URL.revokeObjectURL(url);
#| }
#| }
///|
extern "js" fn request_audio_play(
audio : Audio,
activation_epoch : Int,
) -> Unit =
#| (audio, activationEpoch) => {
#| audio.__selenePlayAttemptEpoch = activationEpoch | 0;
#| if (audio.error) {
#| audio.__selenePlayState = 3;
#| return;
#| }
#| audio.__selenePlayState = 0;
#| const result = audio.play();
#| if (result && typeof result.then === 'function') {
#| result.then(() => {
#| audio.__selenePlayState = 1;
#| }).catch((err) => {
#| const name = err && err.name ? String(err.name) : '';
#| if (name === 'AbortError' && audio.paused) {
#| audio.__selenePlayState = 0;
#| return;
#| }
#| audio.__selenePlayState = name === 'NotAllowedError' ? 2 : 3;
#| });
#| } else {
#| audio.__selenePlayState = audio.paused ? 0 : 1;
#| }
#| }
///|
extern "js" fn audio_play_state(audio : Audio) -> Int =
#| (audio) => {
#| if (audio.error) {
#| return 3;
#| }
#| return audio.__selenePlayState | 0;
#| }
///|
extern "js" fn Audio::clone_audio(self : Self) -> Audio =
#| (self) => {
#| const init = globalThis.__selene_init_audio_element;
#| const clone = new Audio(self.src);
#| return init ? init(clone) : clone;
#| }
///|
extern "js" fn Audio::load(self : Self) -> Unit = "(self) => self.load()"