import type * as p from "@bokehjs/core/properties" import {HTMLBox, HTMLBoxView, set_size} from "./layout" export class AudioView extends HTMLBoxView { declare model: Audio protected audioEl: HTMLAudioElement protected dialogEl: HTMLElement private _blocked: boolean private _time: any private _setting: boolean override initialize(): void { super.initialize() this._blocked = false this._setting = false this._time = Date.now() } override connect_signals(): void { super.connect_signals() const {loop, paused, time, value, volume, muted, autoplay} = this.model.properties this.on_change(loop, () => this.set_loop()) this.on_change(paused, () => this.set_paused()) this.on_change(time, () => this.set_time()) this.on_change(value, () => this.set_value()) this.on_change(volume, () => this.set_volume()) this.on_change(muted, () => this.set_muted()) this.on_change(autoplay, () => this.set_autoplay()) } override render(): void { super.render() this.audioEl = document.createElement("audio") this.audioEl.controls = true this.audioEl.src = this.model.value this.audioEl.currentTime = this.model.time this.audioEl.loop = this.model.loop this.audioEl.muted = this.model.muted this.audioEl.autoplay = this.model.autoplay if (this.model.volume != null) { this.audioEl.volume = this.model.volume/100 } else { this.model.volume = this.audioEl.volume*100 } this.audioEl.onpause = () => this.model.paused = true this.audioEl.onplay = () => this.model.paused = false this.audioEl.ontimeupdate = () => this.update_time(this) this.audioEl.onvolumechange = () => this.update_volume(this) set_size(this.audioEl, this.model, false) this.shadow_el.appendChild(this.audioEl) if (!this.model.paused) { this.audioEl.play() } } update_time(view: AudioView): void { if (view._setting) { view._setting = false return } if ((Date.now() - view._time) < view.model.throttle) { return } view._blocked = true view.model.time = view.audioEl.currentTime view._time = Date.now() } update_volume(view: AudioView): void { if (view._setting) { view._setting = false return } view._blocked = true view.model.volume = view.audioEl.volume*100 } set_loop(): void { this.audioEl.loop = this.model.loop } set_muted(): void { this.audioEl.muted = this.model.muted } set_autoplay(): void { this.audioEl.autoplay = this.model.autoplay } set_paused(): void { if (!this.audioEl.paused && this.model.paused) { this.audioEl.pause() } if (this.audioEl.paused && !this.model.paused) { this.audioEl.play() } } set_volume(): void { if (this._blocked) { this._blocked = false return } this._setting = true if (this.model.volume != null) { this.audioEl.volume = this.model.volume/100 } } set_time(): void { if (this._blocked) { this._blocked = false return } this._setting = true this.audioEl.currentTime = this.model.time } set_value(): void { this.audioEl.src = this.model.value } } export namespace Audio { export type Attrs = p.AttrsOf export type Props = HTMLBox.Props & { loop: p.Property paused: p.Property muted: p.Property autoplay: p.Property time: p.Property throttle: p.Property value: p.Property volume: p.Property } } export interface Audio extends Audio.Attrs {} export class Audio extends HTMLBox { declare properties: Audio.Props constructor(attrs?: Partial) { super(attrs) } static override __module__ = "panel.models.widgets" static { this.prototype.default_view = AudioView this.define(({Any, Bool, Float, Nullable}) => ({ loop: [ Bool, false ], paused: [ Bool, true ], muted: [ Bool, false ], autoplay: [ Bool, false ], time: [ Float, 0 ], throttle: [ Float, 250 ], value: [ Any, "" ], volume: [ Nullable(Float), null ], })) } }