-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refactor: refactor HTMLAudioPlayer #316
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
/* eslint-disable @typescript-eslint/typedef */ | ||
/* eslint-disable @typescript-eslint/explicit-function-return-type */ | ||
|
||
import { Trigger } from "@akashic/trigger"; | ||
import type { HTMLAudioAsset } from "./HTMLAudioAsset"; | ||
import { setupChromeMEIWorkaround } from "./HTMLAudioAutoplayHelper"; | ||
|
||
export interface HTMLAudioPlayerContextParameterObject { | ||
asset: HTMLAudioAsset; | ||
} | ||
|
||
export class HTMLAudioPlayerContext { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 切り出す方針同意なのですが、名前づけが難しいですね。
で "player" と "context" の関係が逆になっているように思います (前者は context が player で実装されている一方、後者は context で player が実装されている) 。 "play context" と "player context" で別の語だと解釈することもできそうですが、名前からはあまり違いが読み取れなさそうです。 コメントされているとおり主眼は この時、名前は There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. おっしゃるとおり 「 名前については変に長くなっても分かりづらいだけな気がしたため |
||
onStop: Trigger<void>; | ||
|
||
asset: HTMLAudioAsset; | ||
element: HTMLAudioElement | null; | ||
offsetStart: number; | ||
offsetEnd: number; | ||
loopOffset: number; | ||
duration: number; | ||
loop: boolean; | ||
|
||
_dummyTimerId: number | null; | ||
_reachEndTimerId: number | null; | ||
_previousCurrentTime: number; | ||
|
||
constructor({ asset }: HTMLAudioPlayerContextParameterObject) { | ||
this.asset = asset; | ||
this.duration = asset.duration ?? +Infinity; | ||
this.offsetStart = asset.offset ?? 0; | ||
this.offsetEnd = this.offsetStart + this.duration; | ||
this.loop = !!asset.loop; | ||
this.loopOffset = asset.loopOffset ?? 0; | ||
this.onStop = new Trigger(); | ||
this._dummyTimerId = null; | ||
this._reachEndTimerId = null; | ||
|
||
const element = asset.cloneElement(); | ||
if (element) { | ||
setupChromeMEIWorkaround(element); | ||
element.addEventListener("timeupdate", this._onTimeupdate, false); | ||
element.addEventListener("ended", this._onEnded, false); | ||
element.currentTime = this.offsetStart / 1000; | ||
} else { | ||
if (!asset.loop && asset.duration != null) { | ||
this._setDummyTimer(this.duration); | ||
} | ||
} | ||
this.element = element; | ||
this._previousCurrentTime = element?.currentTime ?? 0; | ||
} | ||
|
||
rewind() { | ||
this.pause(); | ||
this.setCurrentTime(this.loopOffset || this.offsetStart); | ||
this.play(); | ||
} | ||
|
||
play() { | ||
this.element?.play().catch((_err) => { | ||
// user interact の前に play() を呼ぶとエラーになる。これは HTMLAudioAutoplayHelper で吸収する | ||
}); | ||
} | ||
|
||
pause() { | ||
this.element?.pause(); | ||
this._clearRewindTimer(); | ||
} | ||
|
||
setCurrentTime(offset: number) { | ||
if (!this.element) return; | ||
this.element.currentTime = offset / 1000; | ||
this._previousCurrentTime = this.element.currentTime; | ||
} | ||
|
||
setVolume(volume: number) { | ||
if (!this.element) return; | ||
this.element.volume = volume; | ||
} | ||
|
||
destroy() { | ||
this.onStop.destroy(); | ||
const element = this.element; | ||
if (element) { | ||
element.removeEventListener("timeupdate", this._onTimeupdate, false); | ||
element.removeEventListener("ended", this._onEnded, false); | ||
} | ||
this._clearDummyTimer(); | ||
this._clearRewindTimer(); | ||
} | ||
|
||
_setDummyTimer(duration: number) { | ||
this._clearDummyTimer(); | ||
this._dummyTimerId = window.setTimeout(() => this.pause(), duration); | ||
} | ||
|
||
_clearDummyTimer() { | ||
if (this._dummyTimerId == null) return; | ||
window.clearTimeout(this._dummyTimerId); | ||
this._dummyTimerId = null; | ||
} | ||
|
||
_setRewindTimer(duration: number) { | ||
this._clearRewindTimer(); | ||
this._reachEndTimerId = window.setTimeout(() => this._onReachEnd(), duration); | ||
} | ||
|
||
_clearRewindTimer() { | ||
if (this._reachEndTimerId == null) return; | ||
window.clearTimeout(this._reachEndTimerId); | ||
this._reachEndTimerId = null; | ||
} | ||
|
||
_onReachEnd() { | ||
if (this.loop) { | ||
this.rewind(); | ||
} else { | ||
this.pause(); | ||
this.onStop.fire(); | ||
} | ||
|
||
this._clearRewindTimer(); | ||
} | ||
|
||
_onTimeupdate = () => { | ||
const element = this.element!; // this.element が存在する場合にのみ呼び出される | ||
if (element.paused) return; | ||
|
||
const currentOffset = element.currentTime * 1000; | ||
const deltaSinceLastCall = Math.max(element.currentTime * 1000 - this._previousCurrentTime, 0); | ||
const deltaUntilEnd = Math.max(this.offsetEnd - element.currentTime * 1000, 0); | ||
this._previousCurrentTime = element.currentTime * 1000; | ||
|
||
if (this.offsetEnd < currentOffset + deltaSinceLastCall || this.offsetEnd <= currentOffset) { | ||
this._setRewindTimer(deltaUntilEnd); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
その仮定のもと
するように修正しました。 |
||
} | ||
}; | ||
|
||
_onEnded = () => { | ||
this._onReachEnd(); | ||
}; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
この箇所に対応する、
play()
時のHTMLAudioElement#volume
の設定箇所が消えたように見えますが、外部影響ないでしょうか?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
見落としてました。5c4045f にて修正済みです。