-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathplayer.js
148 lines (117 loc) · 2.95 KB
/
player.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import { getSongs, getArtworks } from "./store.js";
let songs = [];
let artworks = {};
let currentIndex = 0;
async function initializePlaylist() {
songs = await getSongs();
artworks = await getArtworks();
for (const song of songs) {
const artwork = artworks[`${song.artist}-${song.album}`];
if (artwork) {
song.artworkUrl = typeof artwork === 'string' ? artwork : URL.createObjectURL(artwork);
}
}
// If there was a current index set, set it to the correct value.
// The current song might have moved to a new position.
if (currentIndex) {
const currentSong = songs[currentIndex];
if (currentSong) {
currentIndex = songs.indexOf(currentSong);
}
}
}
export class Player extends EventTarget {
constructor() {
super();
this.audio = new Audio();
this.song = null;
this.isPlaying = false;
this.audio.addEventListener('ended', () => {
this.isPlaying = false;
this.playNext();
});
this.audio.addEventListener('error', e => {
this.dispatchEvent(new Event('error'));
});
this.audio.addEventListener('play', e => {
this.dispatchEvent(new Event('playing'));
});
}
async loadPlaylist() {
await initializePlaylist();
return songs;
}
load(song) {
this.song = song;
if (!song.type || song.type === 'url') {
this.audio.src = song.id;
} else if (song.type === 'file') {
const url = URL.createObjectURL(song.data);
this.audio.src = url;
}
this.audio.addEventListener('canplaythrough', () => {
this.dispatchEvent(new Event('canplay'));
}, { once: true });
}
play(song) {
let newSongWasLoaded = false;
if (!songs.length) {
return;
}
// If a specific song is passed, load it first.
if (song) {
this.load(song);
newSongWasLoaded = true;
}
// Otherwise just play the current song.
// Although if none was loaded, then that's the default
// state, and we should load the first song.
if (!this.song) {
this.load(songs[0]);
newSongWasLoaded = true;
}
this.audio.play();
this.isPlaying = true;
currentIndex = songs.indexOf(this.song);
if (!newSongWasLoaded) {
this.dispatchEvent(new Event('canplay'));
}
}
playPrevious() {
if (currentIndex === 0) {
this.play(songs[0]);
}
this.play(songs[currentIndex - 1]);
}
playNext() {
if (currentIndex < songs.length - 1) {
this.play(songs[currentIndex + 1]);
}
}
pause() {
if (!this.song) {
return;
}
this.audio.pause();
this.isPlaying = false;
this.dispatchEvent(new Event('paused'));
}
get volume() {
return this.audio.volume;
}
set volume(volume) {
this.audio.volume = volume;
}
get currentTime() {
return this.audio.currentTime;
}
set currentTime(time) {
if (!this.song) {
return;
}
this.audio.currentTime = time;
}
get duration() {
return this.audio.duration;
}
}