mirror of
https://github.com/kichikuou/xsystem35-sdl2.git
synced 2026-09-30 02:38:10 +03:00
111 lines
3.8 KiB
TypeScript
111 lines
3.8 KiB
TypeScript
/// <reference path="util.ts" />
|
|
/// <reference path="volume.ts" />
|
|
|
|
namespace xsystem35 {
|
|
export class CDPlayer {
|
|
private audio = <HTMLAudioElement>$('audio');
|
|
private blobs: Blob[];
|
|
private currentTrack: number;
|
|
private isVolumeSupported: boolean;
|
|
private unmute: () => void; // Non-null if emulating mute by pause
|
|
waiting: boolean;
|
|
|
|
constructor(private imageLoader: ImageLoader, volumeControl: VolumeControl) {
|
|
// Volume control of <audio> is not supported in iOS
|
|
this.audio.volume = 0.5;
|
|
this.isVolumeSupported = this.audio.volume !== 1;
|
|
|
|
this.blobs = [];
|
|
volumeControl.addEventListener(this.onVolumeChanged.bind(this));
|
|
this.audio.volume = volumeControl.volume();
|
|
this.audio.addEventListener('error', this.onAudioError.bind(this));
|
|
this.waiting = false;
|
|
this.removeUserGestureRestriction();
|
|
if (!this.isVolumeSupported) {
|
|
volumeControl.hideSlider();
|
|
if (this.audio.volume === 0)
|
|
this.unmute = () => {};
|
|
}
|
|
}
|
|
|
|
play(track: number, loop: number) {
|
|
this.currentTrack = track;
|
|
if (this.unmute) {
|
|
this.unmute = () => { this.play(track, loop); };
|
|
return;
|
|
}
|
|
this.waiting = true;
|
|
if (this.blobs[track]) {
|
|
this.startPlayback(this.blobs[track], loop);
|
|
return;
|
|
}
|
|
this.imageLoader.getCDDA(track).then((blob) => {
|
|
this.blobs[track] = blob;
|
|
this.startPlayback(blob, loop);
|
|
});
|
|
}
|
|
|
|
stop() {
|
|
this.audio.pause();
|
|
this.currentTrack = null;
|
|
if (this.unmute)
|
|
this.unmute = () => {};
|
|
}
|
|
|
|
getPosition(): number {
|
|
if (!this.currentTrack)
|
|
return 0;
|
|
let time = Math.round(this.audio.currentTime * 75);
|
|
if (this.unmute || this.audio.error)
|
|
time += 750; // unblock Kichikuou OP
|
|
return this.currentTrack | time << 8;
|
|
}
|
|
|
|
private startPlayback(blob: Blob, loop: number) {
|
|
this.audio.setAttribute('src', URL.createObjectURL(blob));
|
|
this.audio.loop = (loop !== 0);
|
|
this.audio.load();
|
|
this.audio.play();
|
|
this.waiting = false;
|
|
}
|
|
|
|
private onVolumeChanged(evt: CustomEvent) {
|
|
if (this.isVolumeSupported) {
|
|
this.audio.volume = evt.detail;
|
|
return;
|
|
}
|
|
let muted = evt.detail === 0;
|
|
if (!!this.unmute === muted)
|
|
return;
|
|
if (muted) {
|
|
this.audio.pause();
|
|
this.unmute = () => { this.audio.play(); };
|
|
} else {
|
|
let unmute = this.unmute;
|
|
this.unmute = null;
|
|
unmute();
|
|
}
|
|
}
|
|
|
|
private onAudioError(err: ErrorEvent) {
|
|
let clone = document.importNode((<HTMLTemplateElement>$('#cdda-error')).content, true);
|
|
let toast = xsystem35.shell.addToast(clone, 'danger');
|
|
toast.querySelector('.cdda-reload-button').addEventListener('click', () => {
|
|
this.imageLoader.reloadImage().then(() => {
|
|
this.play(this.currentTrack, this.audio.loop ? 1 : 0);
|
|
(<HTMLElement>toast.querySelector('.btn-clear')).click();
|
|
});
|
|
});
|
|
}
|
|
|
|
private removeUserGestureRestriction() {
|
|
let hanlder = () => {
|
|
this.audio.load();
|
|
console.log('CDDA unlocked');
|
|
window.removeEventListener('touchend', hanlder);
|
|
};
|
|
window.addEventListener('touchend', hanlder);
|
|
}
|
|
}
|
|
}
|