@aigamo/nostalgic-diva 0.0.1-alpha.69 → 0.0.1-alpha.70
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/PlayerContainer-COjwHOhq.cjs.map +1 -1
- package/dist/PlayerContainer-VQ3YPGU_.js.map +1 -1
- package/dist/SpotifyPlayer-DUKJP7Jz.cjs +2 -0
- package/dist/SpotifyPlayer-DUKJP7Jz.cjs.map +1 -0
- package/dist/SpotifyPlayer-DbZNyvp-.js +38 -0
- package/dist/SpotifyPlayer-DbZNyvp-.js.map +1 -0
- package/dist/{TwitchPlayer-BeQUOIE3.js → TwitchPlayer-Bn8o_9f5.js} +1 -1
- package/dist/{TwitchPlayer-BeQUOIE3.js.map → TwitchPlayer-Bn8o_9f5.js.map} +1 -1
- package/dist/{TwitchPlayer-Doh6zF0n.cjs → TwitchPlayer-SK7o8pMq.cjs} +1 -1
- package/dist/{TwitchPlayer-Doh6zF0n.cjs.map → TwitchPlayer-SK7o8pMq.cjs.map} +1 -1
- package/dist/{VimeoPlayer-7MjNmmgs.cjs → VimeoPlayer-BySLiRru.cjs} +1 -1
- package/dist/{VimeoPlayer-7MjNmmgs.cjs.map → VimeoPlayer-BySLiRru.cjs.map} +1 -1
- package/dist/{VimeoPlayer-CgWujBXW.js → VimeoPlayer-Cz5hB9JG.js} +1 -1
- package/dist/{VimeoPlayer-CgWujBXW.js.map → VimeoPlayer-Cz5hB9JG.js.map} +1 -1
- package/dist/{YouTubePlayer-CkaOKK_g.js → YouTubePlayer-C_fmW0IS.js} +1 -1
- package/dist/{YouTubePlayer-CkaOKK_g.js.map → YouTubePlayer-C_fmW0IS.js.map} +1 -1
- package/dist/{YouTubePlayer-Clpmqsmv.cjs → YouTubePlayer-vLFVWfOz.cjs} +1 -1
- package/dist/{YouTubePlayer-Clpmqsmv.cjs.map → YouTubePlayer-vLFVWfOz.cjs.map} +1 -1
- package/dist/components/SpotifyPlayer.d.ts +4 -0
- package/dist/controllers/PlayerController.d.ts +1 -1
- package/dist/controllers/SpotifyPlayerController.d.ts +23 -0
- package/dist/controllers/index.d.ts +1 -0
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +102 -45
- package/dist/index.es.js.map +1 -1
- package/dist/services/SpotifyVideoService.d.ts +6 -0
- package/package.json +2 -1
package/dist/index.es.js
CHANGED
|
@@ -102,61 +102,76 @@ var g = s(void 0), _ = ({ children: n, logger: i = r }) => {
|
|
|
102
102
|
extractVideoId(e) {
|
|
103
103
|
return e;
|
|
104
104
|
}
|
|
105
|
-
}, k = /(?:
|
|
105
|
+
}, k = "track|episode|album|playlist|show|artist", A = RegExp(`^https?://open\\.spotify\\.com/(?:intl-[a-z]{2}/)?(${k})/([a-zA-Z0-9]+)`), j = RegExp(`^spotify:(${k}):([a-zA-Z0-9]+)$`), M = class extends y {
|
|
106
|
+
constructor() {
|
|
107
|
+
super("Spotify");
|
|
108
|
+
}
|
|
109
|
+
canPlay(e) {
|
|
110
|
+
return A.test(e) || j.test(e);
|
|
111
|
+
}
|
|
112
|
+
extractVideoId(e) {
|
|
113
|
+
let t = A.exec(e) ?? j.exec(e);
|
|
114
|
+
if (t === null) return;
|
|
115
|
+
let [, n, r] = t;
|
|
116
|
+
return `spotify:${n}:${r}`;
|
|
117
|
+
}
|
|
118
|
+
}, N = /(?:www\.|go\.)?twitch\.tv\/videos\/(\d+)($|\?)/, ee = class extends y {
|
|
106
119
|
constructor() {
|
|
107
120
|
super("Twitch");
|
|
108
121
|
}
|
|
109
122
|
canPlay(e) {
|
|
110
|
-
return
|
|
123
|
+
return N.test(e);
|
|
111
124
|
}
|
|
112
125
|
extractVideoId(e) {
|
|
113
|
-
return
|
|
126
|
+
return N.exec(e)?.[1];
|
|
114
127
|
}
|
|
115
|
-
},
|
|
128
|
+
}, P = /vimeo\.com\/(\d+)$/, F = class extends y {
|
|
116
129
|
constructor() {
|
|
117
130
|
super("Vimeo");
|
|
118
131
|
}
|
|
119
132
|
canPlay(e) {
|
|
120
|
-
return
|
|
133
|
+
return P.test(e);
|
|
121
134
|
}
|
|
122
135
|
extractVideoId(e) {
|
|
123
|
-
return
|
|
136
|
+
return P.exec(e)?.[1];
|
|
124
137
|
}
|
|
125
|
-
},
|
|
138
|
+
}, I = /(?:youtu\.be\/|youtube(?:-nocookie|education)?\.com\/(?:embed\/|v\/|watch\/|watch\?v=|watch\?.+&v=|shorts\/|live\/))((\w|-){11})|youtube\.com\/playlist\?list=|youtube\.com\/user\//, L = [
|
|
126
139
|
new class extends y {
|
|
127
140
|
constructor() {
|
|
128
141
|
super("YouTube");
|
|
129
142
|
}
|
|
130
143
|
canPlay(e) {
|
|
131
|
-
return
|
|
144
|
+
return I.test(e);
|
|
132
145
|
}
|
|
133
146
|
extractVideoId(e) {
|
|
134
|
-
return
|
|
147
|
+
return I.exec(e)?.[1];
|
|
135
148
|
}
|
|
136
149
|
}(),
|
|
137
|
-
new
|
|
138
|
-
new
|
|
150
|
+
new ee(),
|
|
151
|
+
new F(),
|
|
139
152
|
new w(),
|
|
140
153
|
new O(),
|
|
154
|
+
new M(),
|
|
141
155
|
new S(),
|
|
142
156
|
new E()
|
|
143
157
|
];
|
|
144
|
-
function
|
|
145
|
-
return
|
|
158
|
+
function R(e) {
|
|
159
|
+
return L.find((t) => t.canPlay(e));
|
|
146
160
|
}
|
|
147
161
|
//#endregion
|
|
148
162
|
//#region src/components/NostalgicDiva.tsx
|
|
149
|
-
var
|
|
163
|
+
var z = new Map(Object.entries({
|
|
150
164
|
Audio: c(() => import("./AudioPlayer-7plDTn5w.js")),
|
|
151
165
|
Dailymotion: c(() => import("./DailymotionPlayer-4LQmDDSf.js")),
|
|
152
166
|
Niconico: c(() => import("./NiconicoPlayer-GFCXF5V7.js")),
|
|
153
167
|
SoundCloud: c(() => import("./SoundCloudPlayer-Cqo5VU57.js")),
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
168
|
+
Spotify: c(() => import("./SpotifyPlayer-DbZNyvp-.js")),
|
|
169
|
+
Twitch: c(() => import("./TwitchPlayer-Bn8o_9f5.js")),
|
|
170
|
+
Vimeo: c(() => import("./VimeoPlayer-Cz5hB9JG.js")),
|
|
171
|
+
YouTube: c(() => import("./YouTubePlayer-C_fmW0IS.js"))
|
|
157
172
|
}));
|
|
158
|
-
function
|
|
159
|
-
let t =
|
|
173
|
+
function B(e) {
|
|
174
|
+
let t = R(e);
|
|
160
175
|
if (t === void 0) return;
|
|
161
176
|
let { type: n, extractVideoId: r } = t, i = r(e);
|
|
162
177
|
if (i !== void 0) return {
|
|
@@ -164,7 +179,7 @@ function L(e) {
|
|
|
164
179
|
videoId: i
|
|
165
180
|
};
|
|
166
181
|
}
|
|
167
|
-
var
|
|
182
|
+
var V = l(() => /* @__PURE__ */ m("div", {
|
|
168
183
|
style: {
|
|
169
184
|
width: "100%",
|
|
170
185
|
height: "100%"
|
|
@@ -178,15 +193,15 @@ var R = l(() => /* @__PURE__ */ m("div", {
|
|
|
178
193
|
border: 0
|
|
179
194
|
}
|
|
180
195
|
})
|
|
181
|
-
})),
|
|
196
|
+
})), H = l(({ src: t, options: n, onControllerChange: r }) => {
|
|
182
197
|
let i = v(), a = u((e) => {
|
|
183
198
|
i.handleControllerChange(e), r?.(e);
|
|
184
199
|
}, [i, r]);
|
|
185
200
|
i.logger.log(e.Debug, "NostalgicDiva");
|
|
186
|
-
let s =
|
|
187
|
-
if (s === void 0) return i.logger.log(e.Warning, `Failed to extract type and videoId from src: "${t}". Returning EmptyPlayer.`), /* @__PURE__ */ m(
|
|
188
|
-
let { type: c, videoId: l } = s, d =
|
|
189
|
-
return d === void 0 ? (i.logger.log(e.Warning, `No player found for type "${c}" (videoId: "${l}"). Returning EmptyPlayer.`), /* @__PURE__ */ m(
|
|
201
|
+
let s = B(t);
|
|
202
|
+
if (s === void 0) return i.logger.log(e.Warning, `Failed to extract type and videoId from src: "${t}". Returning EmptyPlayer.`), /* @__PURE__ */ m(V, {});
|
|
203
|
+
let { type: c, videoId: l } = s, d = z.get(c);
|
|
204
|
+
return d === void 0 ? (i.logger.log(e.Warning, `No player found for type "${c}" (videoId: "${l}"). Returning EmptyPlayer.`), /* @__PURE__ */ m(V, {})) : /* @__PURE__ */ m(o, {
|
|
190
205
|
fallback: null,
|
|
191
206
|
children: /* @__PURE__ */ m(d, {
|
|
192
207
|
logger: i.logger,
|
|
@@ -196,7 +211,7 @@ var R = l(() => /* @__PURE__ */ m("div", {
|
|
|
196
211
|
options: n
|
|
197
212
|
})
|
|
198
213
|
});
|
|
199
|
-
}),
|
|
214
|
+
}), U = class extends HTMLElement {
|
|
200
215
|
static observedAttributes = ["src"];
|
|
201
216
|
container;
|
|
202
217
|
controller = t;
|
|
@@ -221,7 +236,7 @@ var R = l(() => /* @__PURE__ */ m("div", {
|
|
|
221
236
|
console.debug("[@nostalgic-diva/web-components] handleControllerChange"), this.controller = e;
|
|
222
237
|
};
|
|
223
238
|
#n() {
|
|
224
|
-
h.render(/* @__PURE__ */ m(_, { children: /* @__PURE__ */ m(
|
|
239
|
+
h.render(/* @__PURE__ */ m(_, { children: /* @__PURE__ */ m(H, {
|
|
225
240
|
src: this.src,
|
|
226
241
|
options: this.#e,
|
|
227
242
|
onControllerChange: this.#t
|
|
@@ -276,12 +291,12 @@ var R = l(() => /* @__PURE__ */ m("div", {
|
|
|
276
291
|
return this.controller.supports(e);
|
|
277
292
|
}
|
|
278
293
|
};
|
|
279
|
-
function
|
|
280
|
-
customElements.define("nostalgic-diva",
|
|
294
|
+
function W() {
|
|
295
|
+
customElements.define("nostalgic-diva", U);
|
|
281
296
|
}
|
|
282
297
|
//#endregion
|
|
283
298
|
//#region src/controllers/AudioPlayerController.ts
|
|
284
|
-
var
|
|
299
|
+
var G = class extends i {
|
|
285
300
|
async attach() {
|
|
286
301
|
this.player.onerror = (e) => this.options?.onError?.(e), this.player.onloadeddata = () => this.options?.onLoaded?.({ id: this.player.src }), this.player.onplay = () => this.options?.onPlay?.(), this.player.onpause = () => this.options?.onPause?.(), this.player.onended = () => this.options?.onEnded?.(), this.player.ontimeupdate = () => {
|
|
287
302
|
this.options?.onTimeUpdate?.({
|
|
@@ -330,7 +345,7 @@ var H = class extends i {
|
|
|
330
345
|
async getPlaybackRate() {
|
|
331
346
|
return this.player.playbackRate;
|
|
332
347
|
}
|
|
333
|
-
},
|
|
348
|
+
}, K = [
|
|
334
349
|
"apiready",
|
|
335
350
|
"seeked",
|
|
336
351
|
"video_end",
|
|
@@ -338,7 +353,7 @@ var H = class extends i {
|
|
|
338
353
|
"pause",
|
|
339
354
|
"playing",
|
|
340
355
|
"error"
|
|
341
|
-
],
|
|
356
|
+
], q = class extends i {
|
|
342
357
|
handlePlayerEvents = (e) => {
|
|
343
358
|
switch (e.type) {
|
|
344
359
|
case "apiready":
|
|
@@ -367,10 +382,10 @@ var H = class extends i {
|
|
|
367
382
|
}
|
|
368
383
|
};
|
|
369
384
|
async attach(e) {
|
|
370
|
-
for (let e of
|
|
385
|
+
for (let e of K) this.player.addEventListener(e, this.handlePlayerEvents);
|
|
371
386
|
}
|
|
372
387
|
async detach() {
|
|
373
|
-
for (let e of
|
|
388
|
+
for (let e of K) this.player.removeEventListener(e, this.handlePlayerEvents);
|
|
374
389
|
}
|
|
375
390
|
async loadVideo(e) {
|
|
376
391
|
this.player.load(e);
|
|
@@ -404,9 +419,9 @@ var H = class extends i {
|
|
|
404
419
|
return this.player.muted;
|
|
405
420
|
}
|
|
406
421
|
getPlaybackRate = void 0;
|
|
407
|
-
},
|
|
422
|
+
}, J = /* @__PURE__ */ function(e) {
|
|
408
423
|
return e[e.Play = 2] = "Play", e[e.Pause = 3] = "Pause", e[e.End = 4] = "End", e;
|
|
409
|
-
}(
|
|
424
|
+
}(J || {}), Y = class t extends i {
|
|
410
425
|
static origin = "https://embed.nicovideo.jp";
|
|
411
426
|
duration = 0;
|
|
412
427
|
currentTime = 0;
|
|
@@ -417,10 +432,10 @@ var H = class extends i {
|
|
|
417
432
|
let r = n.data;
|
|
418
433
|
switch (r.eventName) {
|
|
419
434
|
case "playerStatusChange":
|
|
420
|
-
this.logger.log(e.Debug, `player status changed: ${
|
|
435
|
+
this.logger.log(e.Debug, `player status changed: ${J[r.data.playerStatus] ?? r.data.playerStatus}`);
|
|
421
436
|
break;
|
|
422
437
|
case "statusChange":
|
|
423
|
-
switch (this.logger.log(e.Debug, `status changed: ${
|
|
438
|
+
switch (this.logger.log(e.Debug, `status changed: ${J[r.data.playerStatus] ?? r.data.playerStatus}`), r.data.playerStatus) {
|
|
424
439
|
case 2:
|
|
425
440
|
this.options?.onPlay?.();
|
|
426
441
|
break;
|
|
@@ -512,7 +527,7 @@ var H = class extends i {
|
|
|
512
527
|
return this.muted;
|
|
513
528
|
}
|
|
514
529
|
getPlaybackRate = void 0;
|
|
515
|
-
},
|
|
530
|
+
}, X = class e extends i {
|
|
516
531
|
getDurationCore() {
|
|
517
532
|
return new Promise((e, t) => {
|
|
518
533
|
this.player.getDuration(e);
|
|
@@ -581,7 +596,49 @@ var H = class extends i {
|
|
|
581
596
|
}
|
|
582
597
|
getMuted = void 0;
|
|
583
598
|
getPlaybackRate = void 0;
|
|
584
|
-
},
|
|
599
|
+
}, Z = class extends i {
|
|
600
|
+
duration = 0;
|
|
601
|
+
position = 0;
|
|
602
|
+
previousIsPaused = !0;
|
|
603
|
+
currentUri;
|
|
604
|
+
ended = !1;
|
|
605
|
+
handlePlaybackUpdate = (e) => {
|
|
606
|
+
let { position: t, duration: n, isPaused: r, playingURI: i } = e.data;
|
|
607
|
+
i !== this.currentUri && (this.currentUri = i, this.ended = !1), this.position = t, this.duration = n, this.options?.onTimeUpdate?.({
|
|
608
|
+
duration: n / 1e3,
|
|
609
|
+
percent: n > 0 ? t / n : 0,
|
|
610
|
+
seconds: t / 1e3
|
|
611
|
+
}), r !== this.previousIsPaused && (this.previousIsPaused = r, r ? this.options?.onPause?.() : this.options?.onPlay?.()), n > 0 && t >= n ? this.ended || (this.ended = !0, this.options?.onEnded?.()) : this.ended = !1;
|
|
612
|
+
};
|
|
613
|
+
async attach(e) {
|
|
614
|
+
this.player.addListener("ready", () => this.options?.onLoaded?.({ id: e })), this.player.addListener("playback_update", this.handlePlaybackUpdate);
|
|
615
|
+
}
|
|
616
|
+
async detach() {}
|
|
617
|
+
async loadVideo(e) {
|
|
618
|
+
this.duration = 0, this.position = 0, this.previousIsPaused = !0, this.player.loadUri(e), this.options?.onLoaded?.({ id: e });
|
|
619
|
+
}
|
|
620
|
+
async play() {
|
|
621
|
+
this.player.resume();
|
|
622
|
+
}
|
|
623
|
+
async pause() {
|
|
624
|
+
this.player.pause();
|
|
625
|
+
}
|
|
626
|
+
async setCurrentTime(e) {
|
|
627
|
+
e <= 0 ? this.player.restart() : this.player.seek(e);
|
|
628
|
+
}
|
|
629
|
+
setVolume = void 0;
|
|
630
|
+
setMuted = void 0;
|
|
631
|
+
setPlaybackRate = void 0;
|
|
632
|
+
async getDuration() {
|
|
633
|
+
return this.duration / 1e3;
|
|
634
|
+
}
|
|
635
|
+
async getCurrentTime() {
|
|
636
|
+
return this.position / 1e3;
|
|
637
|
+
}
|
|
638
|
+
getVolume = void 0;
|
|
639
|
+
getMuted = void 0;
|
|
640
|
+
getPlaybackRate = void 0;
|
|
641
|
+
}, Q = class extends i {
|
|
585
642
|
handleReady = () => {
|
|
586
643
|
this.options?.onLoaded?.({ id: this.player.getVideo() });
|
|
587
644
|
};
|
|
@@ -637,7 +694,7 @@ var H = class extends i {
|
|
|
637
694
|
return this.player.getMuted();
|
|
638
695
|
}
|
|
639
696
|
getPlaybackRate = void 0;
|
|
640
|
-
},
|
|
697
|
+
}, te = class extends i {
|
|
641
698
|
async attach() {
|
|
642
699
|
await this.player.ready(), this.player.on("error", (e) => this.options?.onError?.(e)), this.player.on("loaded", (e) => this.options?.onLoaded?.({ id: e.id.toString() })), this.player.on("play", () => this.options?.onPlay?.()), this.player.on("pause", () => this.options?.onPause?.()), this.player.on("ended", () => this.options?.onEnded?.()), this.player.on("timeupdate", (e) => {
|
|
643
700
|
this.options?.onTimeUpdate?.({
|
|
@@ -686,9 +743,9 @@ var H = class extends i {
|
|
|
686
743
|
async getPlaybackRate() {
|
|
687
744
|
return this.player.getPlaybackRate();
|
|
688
745
|
}
|
|
689
|
-
},
|
|
746
|
+
}, $ = /* @__PURE__ */ function(e) {
|
|
690
747
|
return e[e.UNSTARTED = -1] = "UNSTARTED", e[e.ENDED = 0] = "ENDED", e[e.PLAYING = 1] = "PLAYING", e[e.PAUSED = 2] = "PAUSED", e[e.BUFFERING = 3] = "BUFFERING", e[e.CUED = 5] = "CUED", e;
|
|
691
|
-
}(
|
|
748
|
+
}($ || {}), ne = class extends i {
|
|
692
749
|
previousTime;
|
|
693
750
|
timeUpdateIntervalId;
|
|
694
751
|
clearTimeUpdateInterval() {
|
|
@@ -711,7 +768,7 @@ var H = class extends i {
|
|
|
711
768
|
return new Promise((n, r) => {
|
|
712
769
|
this.player.addEventListener("onReady", async () => {
|
|
713
770
|
this.player.addEventListener("onError", (e) => this.options?.onError?.(e.data)), this.player.addEventListener("onStateChange", (n) => {
|
|
714
|
-
switch (this.logger.log(e.Debug, `state changed: ${
|
|
771
|
+
switch (this.logger.log(e.Debug, `state changed: ${$[n.data]}`), n.data) {
|
|
715
772
|
case YT.PlayerState.CUED:
|
|
716
773
|
this.options?.onLoaded?.({ id: t });
|
|
717
774
|
break;
|
|
@@ -770,6 +827,6 @@ var H = class extends i {
|
|
|
770
827
|
}
|
|
771
828
|
};
|
|
772
829
|
//#endregion
|
|
773
|
-
export {
|
|
830
|
+
export { G as AudioPlayerController, q as DailymotionPlayerController, e as LogLevel, Y as NiconicoPlayerController, H as NostalgicDiva, U as NostalgicDivaElement, _ as NostalgicDivaProvider, a as PlayerContainer, n as PlayerController, i as PlayerControllerImpl, X as SoundCloudPlayerController, Z as SpotifyPlayerController, Q as TwitchPlayerController, y as VideoService, te as VimeoPlayerController, ne as YouTubePlayerController, r as defaultLogger, W as defineNostalgicDiva, R as findVideoService, t as nullPlayerController, z as players, v as useNostalgicDiva, L as videoServices };
|
|
774
831
|
|
|
775
832
|
//# sourceMappingURL=index.es.js.map
|
package/dist/index.es.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.es.js","names":["#options","#handleControllerChange","#render"],"sources":["../src/components/NostalgicDivaProvider.tsx","../src/services/VideoService.ts","../src/services/AudioVideoService.ts","../src/services/DailymotionVideoService.ts","../src/services/NiconicoVideoService.ts","../src/services/SoundCloudVideoService.ts","../src/services/TwitchVideoService.ts","../src/services/VimeoVideoService.ts","../src/services/YouTubeVideoService.ts","../src/services/findVideoService.ts","../src/components/NostalgicDiva.tsx","../src/components/defineNostalgicDiva.tsx","../src/controllers/AudioPlayerController.ts","../src/controllers/DailymotionPlayerController.ts","../src/controllers/NiconicoPlayerController.ts","../src/controllers/SoundCloudPlayerController.ts","../src/controllers/TwitchPlayerController.ts","../src/controllers/VimeoPlayerController.ts","../src/controllers/YouTubePlayerController.ts"],"sourcesContent":["import { type ILogger, LogLevel, defaultLogger } from '@/controllers/Logger';\nimport { nullPlayerController } from '@/controllers/NullPlayerController';\nimport type {\n\tIPlayerCommands,\n\tIPlayerController,\n} from '@/controllers/PlayerController';\nimport {\n\ttype ReactElement,\n\ttype ReactNode,\n\tcreateContext,\n\tuseCallback,\n\tuseContext,\n\tuseMemo,\n\tuseRef,\n} from 'react';\n\ninterface NostalgicDivaContextProps extends IPlayerController {\n\tlogger: ILogger;\n\thandleControllerChange: (value: IPlayerController) => void;\n}\n\nconst NostalgicDivaContext = createContext<NostalgicDivaContextProps>(\n\tundefined!,\n);\n\nexport interface NostalgicDivaProviderProps {\n\tchildren?: ReactNode;\n\tlogger?: ILogger;\n}\n\nexport const NostalgicDivaProvider = ({\n\tchildren,\n\tlogger = defaultLogger,\n}: NostalgicDivaProviderProps): ReactElement => {\n\tconst controllerRef = useRef<IPlayerController>(nullPlayerController);\n\n\tconst handleControllerChange = useCallback(\n\t\t(value: IPlayerController): void => {\n\t\t\tlogger.log(\n\t\t\t\tLogLevel.Debug,\n\t\t\t\t'NostalgicDivaProvider.handleControllerChange',\n\t\t\t\tcontrollerRef.current,\n\t\t\t\tvalue,\n\t\t\t);\n\n\t\t\tcontrollerRef.current = value;\n\t\t},\n\t\t[logger],\n\t);\n\n\tconst loadVideo = useCallback(\n\t\tasync (id: string): Promise<void> => {\n\t\t\tlogger.log(\n\t\t\t\tLogLevel.Debug,\n\t\t\t\t'NostalgicDivaProvider.loadVideo',\n\t\t\t\tcontrollerRef.current,\n\t\t\t);\n\n\t\t\tawait controllerRef.current.loadVideo(id);\n\t\t},\n\t\t[logger],\n\t);\n\n\tconst play = useCallback(async (): Promise<void> => {\n\t\tlogger.log(\n\t\t\tLogLevel.Debug,\n\t\t\t'NostalgicDivaProvider.play',\n\t\t\tcontrollerRef.current,\n\t\t);\n\n\t\tawait controllerRef.current.play();\n\t}, [logger]);\n\n\tconst pause = useCallback(async (): Promise<void> => {\n\t\tlogger.log(\n\t\t\tLogLevel.Debug,\n\t\t\t'NostalgicDivaProvider.pause',\n\t\t\tcontrollerRef.current,\n\t\t);\n\n\t\tawait controllerRef.current.pause();\n\t}, [logger]);\n\n\tconst setCurrentTime = useCallback(\n\t\tasync (seconds: number): Promise<void> => {\n\t\t\tlogger.log(\n\t\t\t\tLogLevel.Debug,\n\t\t\t\t'NostalgicDivaProvider.setCurrentTime',\n\t\t\t\tcontrollerRef.current,\n\t\t\t);\n\n\t\t\tawait controllerRef.current.setCurrentTime(seconds);\n\t\t\tawait controllerRef.current.play();\n\t\t},\n\t\t[logger],\n\t);\n\n\tconst setVolume = useCallback(\n\t\tasync (volume: number): Promise<void> => {\n\t\t\tlogger.log(\n\t\t\t\tLogLevel.Debug,\n\t\t\t\t'NostalgicDivaProvider.setVolume',\n\t\t\t\tcontrollerRef.current,\n\t\t\t);\n\n\t\t\tawait controllerRef.current.setVolume(volume);\n\t\t},\n\t\t[logger],\n\t);\n\n\tconst setMuted = useCallback(\n\t\tasync (muted: boolean): Promise<void> => {\n\t\t\tlogger.log(\n\t\t\t\tLogLevel.Debug,\n\t\t\t\t'NostalgicDivaProvider.setMuted',\n\t\t\t\tcontrollerRef.current,\n\t\t\t);\n\n\t\t\tawait controllerRef.current.setMuted(muted);\n\t\t},\n\t\t[logger],\n\t);\n\n\tconst setPlaybackRate = useCallback(\n\t\tasync (playbackRate: number): Promise<void> => {\n\t\t\tlogger.log(\n\t\t\t\tLogLevel.Debug,\n\t\t\t\t'NostalgicDivaProvider.setPlaybackRate',\n\t\t\t\tcontrollerRef.current,\n\t\t\t);\n\n\t\t\tawait controllerRef.current.setPlaybackRate(playbackRate);\n\t\t},\n\t\t[logger],\n\t);\n\n\tconst getDuration = useCallback(async (): Promise<number> => {\n\t\tlogger.log(\n\t\t\tLogLevel.Debug,\n\t\t\t'NostalgicDivaProvider.getDuration',\n\t\t\tcontrollerRef.current,\n\t\t);\n\n\t\treturn await controllerRef.current.getDuration();\n\t}, [logger]);\n\n\tconst getCurrentTime = useCallback(async (): Promise<number> => {\n\t\tlogger.log(\n\t\t\tLogLevel.Debug,\n\t\t\t'NostalgicDivaProvider.getCurrentTime',\n\t\t\tcontrollerRef.current,\n\t\t);\n\n\t\treturn await controllerRef.current.getCurrentTime();\n\t}, [logger]);\n\n\tconst getVolume = useCallback(async (): Promise<number> => {\n\t\tlogger.log(\n\t\t\tLogLevel.Debug,\n\t\t\t'NostalgicDivaProvider.getVolume',\n\t\t\tcontrollerRef.current,\n\t\t);\n\n\t\treturn await controllerRef.current.getVolume();\n\t}, [logger]);\n\n\tconst getMuted = useCallback(async (): Promise<boolean> => {\n\t\tlogger.log(\n\t\t\tLogLevel.Debug,\n\t\t\t'NostalgicDivaProvider.getMuted',\n\t\t\tcontrollerRef.current,\n\t\t);\n\n\t\treturn await controllerRef.current.getMuted();\n\t}, [logger]);\n\n\tconst getPlaybackRate = useCallback(async (): Promise<number> => {\n\t\tlogger.log(\n\t\t\tLogLevel.Debug,\n\t\t\t'NostalgicDivaProvider.getPlaybackRate',\n\t\t\tcontrollerRef.current,\n\t\t);\n\n\t\treturn await controllerRef.current.getPlaybackRate();\n\t}, [logger]);\n\n\tconst supports = useCallback(\n\t\t(command: keyof IPlayerCommands): boolean =>\n\t\t\tcontrollerRef.current.supports(command),\n\t\t[],\n\t);\n\n\tconst value = useMemo(\n\t\t(): NostalgicDivaContextProps => ({\n\t\t\tlogger,\n\t\t\thandleControllerChange,\n\t\t\tloadVideo,\n\t\t\tplay,\n\t\t\tpause,\n\t\t\tsetCurrentTime,\n\t\t\tsetVolume,\n\t\t\tsetMuted,\n\t\t\tsetPlaybackRate,\n\t\t\tgetDuration,\n\t\t\tgetCurrentTime,\n\t\t\tgetVolume,\n\t\t\tgetMuted,\n\t\t\tgetPlaybackRate,\n\t\t\tsupports,\n\t\t}),\n\t\t[\n\t\t\tlogger,\n\t\t\thandleControllerChange,\n\t\t\tloadVideo,\n\t\t\tplay,\n\t\t\tpause,\n\t\t\tsetCurrentTime,\n\t\t\tsetVolume,\n\t\t\tsetMuted,\n\t\t\tsetPlaybackRate,\n\t\t\tgetDuration,\n\t\t\tgetCurrentTime,\n\t\t\tgetVolume,\n\t\t\tgetMuted,\n\t\t\tgetPlaybackRate,\n\t\t\tsupports,\n\t\t],\n\t);\n\n\treturn (\n\t\t<NostalgicDivaContext.Provider value={value}>\n\t\t\t{children}\n\t\t</NostalgicDivaContext.Provider>\n\t);\n};\n\nexport const useNostalgicDiva = (): NostalgicDivaContextProps => {\n\treturn useContext(NostalgicDivaContext);\n};\n","import type { PlayerType } from '@/controllers/PlayerController';\n\nexport abstract class VideoService {\n\tprotected constructor(readonly type: PlayerType) {}\n\n\tabstract canPlay(url: string): boolean;\n\n\tabstract extractVideoId(url: string): string | undefined;\n}\n","import { VideoService } from '@/services/VideoService';\n\n// https://github.com/cookpete/react-player/blob/2811bc59b9368170acc20d4f1e39555413d0d9e1/src/patterns.js\nconst AUDIO_EXTENSIONS =\n\t/\\.(m4a|m4b|mp4a|mpga|mp2|mp2a|mp3|m2a|m3a|wav|weba|aac|oga|spx)($|\\?)/i;\nconst VIDEO_EXTENSIONS = /\\.(mp4|og[gv]|webm|mov|m4v)(#t=[,\\d+]+)?($|\\?)/i;\n\nexport class AudioVideoService extends VideoService {\n\tconstructor() {\n\t\tsuper('Audio');\n\t}\n\n\tcanPlay(url: string): boolean {\n\t\treturn AUDIO_EXTENSIONS.test(url) || VIDEO_EXTENSIONS.test(url);\n\t}\n\n\textractVideoId(url: string): string | undefined {\n\t\treturn url;\n\t}\n}\n","import { VideoService } from '@/services/VideoService';\n\n// https://github.com/cookpete/react-player/blob/2811bc59b9368170acc20d4f1e39555413d0d9e1/src/patterns.js\nconst MATCH_URL_DAILYMOTION =\n\t/^(?:(?:https?):)?(?:\\/\\/)?(?:www\\.)?(?:(?:dailymotion\\.com(?:\\/embed)?\\/video)|dai\\.ly)\\/([a-zA-Z0-9]+)(?:_[\\w_-]+)?(?:[\\w.#_-]+)?/;\n\nexport class DailymotionVideoService extends VideoService {\n\tconstructor() {\n\t\tsuper('Dailymotion');\n\t}\n\n\tcanPlay(url: string): boolean {\n\t\treturn MATCH_URL_DAILYMOTION.test(url);\n\t}\n\n\textractVideoId(url: string): string | undefined {\n\t\tconst matches = MATCH_URL_DAILYMOTION.exec(url);\n\t\treturn matches?.[1];\n\t}\n}\n","import { VideoService } from '@/services/VideoService';\n\nconst MATCH_URL_NICONICO = /(?:www\\.|)?nicovideo\\.jp\\/watch\\/(\\w+)$/;\n\nexport class NiconicoVideoService extends VideoService {\n\tconstructor() {\n\t\tsuper('Niconico');\n\t}\n\n\tcanPlay(url: string): boolean {\n\t\treturn MATCH_URL_NICONICO.test(url);\n\t}\n\n\textractVideoId(url: string): string | undefined {\n\t\tconst matches = MATCH_URL_NICONICO.exec(url);\n\t\treturn matches?.[1];\n\t}\n}\n","import { VideoService } from '@/services/VideoService';\n\n// https://github.com/cookpete/react-player/blob/2811bc59b9368170acc20d4f1e39555413d0d9e1/src/patterns.js\nconst MATCH_URL_SOUNDCLOUD = /(?:soundcloud\\.com|snd\\.sc)\\/[^.]+$/;\n\nexport class SoundCloudVideoService extends VideoService {\n\tconstructor() {\n\t\tsuper('SoundCloud');\n\t}\n\n\tcanPlay(url: string): boolean {\n\t\treturn MATCH_URL_SOUNDCLOUD.test(url);\n\t}\n\n\textractVideoId(url: string): string | undefined {\n\t\treturn url;\n\t}\n}\n","import { VideoService } from '@/services/VideoService';\n\n// https://github.com/cookpete/react-player/blob/2811bc59b9368170acc20d4f1e39555413d0d9e1/src/patterns.js\nconst MATCH_URL_TWITCH_VIDEO = /(?:www\\.|go\\.)?twitch\\.tv\\/videos\\/(\\d+)($|\\?)/;\n\nexport class TwitchVideoService extends VideoService {\n\tconstructor() {\n\t\tsuper('Twitch');\n\t}\n\n\tcanPlay(url: string): boolean {\n\t\treturn MATCH_URL_TWITCH_VIDEO.test(url);\n\t}\n\n\textractVideoId(url: string): string | undefined {\n\t\tconst matches = MATCH_URL_TWITCH_VIDEO.exec(url);\n\t\treturn matches?.[1];\n\t}\n}\n","import { VideoService } from '@/services/VideoService';\n\n// https://github.com/cookpete/react-player/blob/2811bc59b9368170acc20d4f1e39555413d0d9e1/src/patterns.js\nconst MATCH_URL_VIMEO = /vimeo\\.com\\/(\\d+)$/;\n\nexport class VimeoVideoService extends VideoService {\n\tconstructor() {\n\t\tsuper('Vimeo');\n\t}\n\n\tcanPlay(url: string): boolean {\n\t\treturn MATCH_URL_VIMEO.test(url);\n\t}\n\n\textractVideoId(url: string): string | undefined {\n\t\treturn MATCH_URL_VIMEO.exec(url)?.[1];\n\t}\n}\n","import { VideoService } from '@/services/VideoService';\n\n// https://github.com/cookpete/react-player/blob/2811bc59b9368170acc20d4f1e39555413d0d9e1/src/patterns.js\nconst MATCH_URL_YOUTUBE =\n\t/(?:youtu\\.be\\/|youtube(?:-nocookie|education)?\\.com\\/(?:embed\\/|v\\/|watch\\/|watch\\?v=|watch\\?.+&v=|shorts\\/|live\\/))((\\w|-){11})|youtube\\.com\\/playlist\\?list=|youtube\\.com\\/user\\//;\n\nexport class YouTubeVideoService extends VideoService {\n\tconstructor() {\n\t\tsuper('YouTube');\n\t}\n\n\tcanPlay(url: string): boolean {\n\t\treturn MATCH_URL_YOUTUBE.test(url);\n\t}\n\n\textractVideoId(url: string): string | undefined {\n\t\tconst matches = MATCH_URL_YOUTUBE.exec(url);\n\t\treturn matches?.[1];\n\t}\n}\n","import { AudioVideoService } from '@/services/AudioVideoService';\nimport { DailymotionVideoService } from '@/services/DailymotionVideoService';\nimport { NiconicoVideoService } from '@/services/NiconicoVideoService';\nimport { SoundCloudVideoService } from '@/services/SoundCloudVideoService';\nimport { TwitchVideoService } from '@/services/TwitchVideoService';\nimport type { VideoService } from '@/services/VideoService';\nimport { VimeoVideoService } from '@/services/VimeoVideoService';\nimport { YouTubeVideoService } from '@/services/YouTubeVideoService';\n\nexport const videoServices: VideoService[] = [\n\tnew YouTubeVideoService(),\n\tnew TwitchVideoService(),\n\tnew VimeoVideoService(),\n\tnew DailymotionVideoService(),\n\tnew SoundCloudVideoService(),\n\tnew AudioVideoService(),\n\tnew NiconicoVideoService(),\n];\n\nexport function findVideoService(url: string): VideoService | undefined {\n\treturn videoServices.find((videoService) => videoService.canPlay(url));\n}\n","import { useNostalgicDiva } from '@/components/NostalgicDivaProvider';\nimport type { PlayerProps } from '@/components/PlayerContainer';\nimport { LogLevel } from '@/controllers/Logger';\nimport type {\n\tIPlayerController,\n\tPlayerOptions,\n\tPlayerType,\n} from '@/controllers/PlayerController';\nimport { findVideoService } from '@/services/findVideoService';\nimport {\n\ttype ElementType,\n\ttype ReactElement,\n\tSuspense,\n\tlazy,\n\tmemo,\n\tuseCallback,\n} from 'react';\n\nexport const players: Map<PlayerType, ElementType<PlayerProps>> = new Map(\n\tObject.entries({\n\t\tAudio: lazy(() => import('./AudioPlayer')),\n\t\tDailymotion: lazy(() => import('./DailymotionPlayer')),\n\t\tNiconico: lazy(() => import('./NiconicoPlayer')),\n\t\tSoundCloud: lazy(() => import('./SoundCloudPlayer')),\n\t\tTwitch: lazy(() => import('./TwitchPlayer')),\n\t\tVimeo: lazy(() => import('./VimeoPlayer')),\n\t\tYouTube: lazy(() => import('./YouTubePlayer')),\n\t}),\n);\n\nexport interface NostalgicDivaProps {\n\tsrc: string;\n\toptions?: PlayerOptions;\n\tonControllerChange?: (value: IPlayerController) => void;\n}\n\nfunction getTypeAndVideoId(\n\turl: string,\n): { type: PlayerType; videoId: string } | undefined {\n\tconst videoService = findVideoService(url);\n\tif (videoService === undefined) {\n\t\treturn undefined;\n\t}\n\n\tconst { type, extractVideoId } = videoService;\n\n\tconst videoId = extractVideoId(url);\n\tif (videoId === undefined) {\n\t\treturn undefined;\n\t}\n\n\treturn { type: type, videoId: videoId };\n}\n\nconst EmptyPlayer = memo((): ReactElement => {\n\treturn (\n\t\t<div style={{ width: '100%', height: '100%' }}>\n\t\t\t<iframe\n\t\t\t\tsrc=\"about:blank\"\n\t\t\t\ttitle=\"about:blank\"\n\t\t\t\tstyle={{\n\t\t\t\t\twidth: '100%',\n\t\t\t\t\theight: '100%',\n\t\t\t\t\tborder: 0,\n\t\t\t\t}}\n\t\t\t/>\n\t\t</div>\n\t);\n});\n\nexport const NostalgicDiva = memo(\n\t({\n\t\tsrc,\n\t\toptions,\n\t\tonControllerChange,\n\t}: NostalgicDivaProps): ReactElement => {\n\t\tconst diva = useNostalgicDiva();\n\n\t\tconst handleControllerChange = useCallback(\n\t\t\t(value: IPlayerController) => {\n\t\t\t\tdiva.handleControllerChange(value);\n\n\t\t\t\tonControllerChange?.(value);\n\t\t\t},\n\t\t\t[diva, onControllerChange],\n\t\t);\n\n\t\tdiva.logger.log(LogLevel.Debug, 'NostalgicDiva');\n\n\t\tconst typeAndVideoId = getTypeAndVideoId(src);\n\t\tif (typeAndVideoId === undefined) {\n\t\t\tdiva.logger.log(\n\t\t\t\tLogLevel.Warning,\n\t\t\t\t`Failed to extract type and videoId from src: \"${src}\". Returning EmptyPlayer.`,\n\t\t\t);\n\t\t\treturn <EmptyPlayer />;\n\t\t}\n\n\t\tconst { type, videoId } = typeAndVideoId;\n\n\t\tconst Player = players.get(type);\n\t\tif (Player === undefined) {\n\t\t\tdiva.logger.log(\n\t\t\t\tLogLevel.Warning,\n\t\t\t\t`No player found for type \"${type}\" (videoId: \"${videoId}\"). Returning EmptyPlayer.`,\n\t\t\t);\n\t\t\treturn <EmptyPlayer />;\n\t\t}\n\n\t\treturn (\n\t\t\t<Suspense fallback={null}>\n\t\t\t\t<Player\n\t\t\t\t\tlogger={diva.logger}\n\t\t\t\t\ttype={type}\n\t\t\t\t\tonControllerChange={handleControllerChange}\n\t\t\t\t\tvideoId={videoId}\n\t\t\t\t\toptions={options}\n\t\t\t\t/>\n\t\t\t</Suspense>\n\t\t);\n\t},\n);\n","import { NostalgicDiva } from '@/components/NostalgicDiva';\nimport { NostalgicDivaProvider } from '@/components/NostalgicDivaProvider';\nimport { nullPlayerController } from '@/controllers/NullPlayerController';\nimport type {\n\tIPlayerCommands,\n\tIPlayerController,\n\tPlayerOptions,\n} from '@/controllers/PlayerController';\nimport ReactDOM from 'react-dom';\n\nexport class NostalgicDivaElement\n\textends HTMLElement\n\timplements IPlayerController\n{\n\tstatic readonly observedAttributes = ['src'];\n\n\tcontainer: ShadowRoot;\n\tcontroller: IPlayerController = nullPlayerController;\n\n\tconstructor() {\n\t\tsuper();\n\n\t\tthis.container = this.attachShadow({ mode: 'closed' });\n\t}\n\n\tget src(): string {\n\t\treturn this.getAttribute('src') ?? '';\n\t}\n\n\tset src(value: string) {\n\t\tthis.setAttribute('src', value);\n\t}\n\n\treadonly #options: PlayerOptions = {\n\t\tonError: (e) =>\n\t\t\tthis.dispatchEvent(new CustomEvent('error', { detail: e })),\n\t\tonLoaded: (e) =>\n\t\t\tthis.dispatchEvent(new CustomEvent('loaded', { detail: e })),\n\t\tonPlay: () => this.dispatchEvent(new CustomEvent('play')),\n\t\tonPause: () => this.dispatchEvent(new CustomEvent('pause')),\n\t\tonEnded: () => this.dispatchEvent(new CustomEvent('ended')),\n\t\tonTimeUpdate: (e) =>\n\t\t\tthis.dispatchEvent(new CustomEvent('timeupdate', { detail: e })),\n\t};\n\n\t#handleControllerChange = (value: IPlayerController): void => {\n\t\tconsole.debug(\n\t\t\t'[@nostalgic-diva/web-components] handleControllerChange',\n\t\t);\n\n\t\tthis.controller = value;\n\t};\n\n\t#render(): void {\n\t\tReactDOM.render(\n\t\t\t<NostalgicDivaProvider>\n\t\t\t\t<NostalgicDiva\n\t\t\t\t\tsrc={this.src}\n\t\t\t\t\toptions={this.#options}\n\t\t\t\t\tonControllerChange={this.#handleControllerChange}\n\t\t\t\t/>\n\t\t\t</NostalgicDivaProvider>,\n\t\t\tthis.container,\n\t\t);\n\t}\n\n\tconnectedCallback(): void {\n\t\tconsole.debug('[@nostalgic-diva/web-components] connectedCallback');\n\n\t\tthis.#render();\n\t}\n\n\tdisconnectedCallback(): void {\n\t\tconsole.debug('[@nostalgic-diva/web-components] disconnectedCallback');\n\t}\n\n\tattributeChangedCallback(): void {\n\t\tconsole.debug(\n\t\t\t'[@nostalgic-diva/web-components] attributeChangedCallback',\n\t\t);\n\n\t\tthis.#render();\n\t}\n\n\tasync loadVideo(id: string): Promise<void> {\n\t\tawait this.controller.loadVideo(id);\n\t}\n\n\tasync play(): Promise<void> {\n\t\tawait this.controller.play();\n\t}\n\n\tasync pause(): Promise<void> {\n\t\tawait this.controller.pause();\n\t}\n\n\tasync setCurrentTime(seconds: number): Promise<void> {\n\t\tawait this.controller.setCurrentTime(seconds);\n\t}\n\n\tasync setVolume(volume: number): Promise<void> {\n\t\tawait this.controller.setVolume(volume);\n\t}\n\n\tasync setMuted(muted: boolean): Promise<void> {\n\t\tawait this.controller.setMuted(muted);\n\t}\n\n\tasync setPlaybackRate(playbackRate: number): Promise<void> {\n\t\tawait this.controller.setPlaybackRate(playbackRate);\n\t}\n\n\tasync getDuration(): Promise<number> {\n\t\treturn await this.controller.getDuration();\n\t}\n\n\tasync getCurrentTime(): Promise<number> {\n\t\treturn await this.controller.getCurrentTime();\n\t}\n\n\tasync getVolume(): Promise<number> {\n\t\treturn await this.controller.getVolume();\n\t}\n\n\tasync getMuted(): Promise<boolean> {\n\t\treturn await this.controller.getMuted();\n\t}\n\n\tasync getPlaybackRate(): Promise<number> {\n\t\treturn await this.controller.getPlaybackRate();\n\t}\n\n\tsupports(command: keyof IPlayerCommands): boolean {\n\t\treturn this.controller.supports(command);\n\t}\n}\n\nexport function defineNostalgicDiva(): void {\n\tcustomElements.define('nostalgic-diva', NostalgicDivaElement);\n}\n","import { PlayerControllerImpl } from '@/controllers/PlayerControllerImpl';\n\n// https://github.com/VocaDB/vocadb/blob/61b8c54f3eca906a477101dab4fdd9b154be310e/VocaDbWeb/Scripts/ViewModels/PVs/PVPlayerFile.ts.\nexport class AudioPlayerController extends PlayerControllerImpl<HTMLAudioElement> {\n\tasync attach(): Promise<void> {\n\t\tthis.player.onerror = (event): void => this.options?.onError?.(event);\n\t\tthis.player.onloadeddata = (): void =>\n\t\t\tthis.options?.onLoaded?.({ id: this.player.src });\n\t\tthis.player.onplay = (): void => this.options?.onPlay?.();\n\t\tthis.player.onpause = (): void => this.options?.onPause?.();\n\t\tthis.player.onended = (): void => this.options?.onEnded?.();\n\t\tthis.player.ontimeupdate = (): void => {\n\t\t\tthis.options?.onTimeUpdate?.({\n\t\t\t\tduration: this.player.duration,\n\t\t\t\tpercent: this.player.currentTime / this.player.duration,\n\t\t\t\tseconds: this.player.currentTime,\n\t\t\t});\n\t\t};\n\t}\n\n\tasync detach(): Promise<void> {\n\t\tthis.player.onerror = null;\n\t\tthis.player.onloadeddata = null;\n\t\tthis.player.onplay = null;\n\t\tthis.player.onpause = null;\n\t\tthis.player.onended = null;\n\t\tthis.player.ontimeupdate = null;\n\t}\n\n\tasync loadVideo(id: string): Promise<void> {\n\t\tthis.player.src = id;\n\t}\n\n\tasync play(): Promise<void> {\n\t\tawait this.player.play();\n\t}\n\n\tasync pause(): Promise<void> {\n\t\tthis.player.pause();\n\t}\n\n\tasync setCurrentTime(seconds: number): Promise<void> {\n\t\tthis.player.currentTime = seconds;\n\t}\n\n\tasync setVolume(volume: number): Promise<void> {\n\t\tthis.player.volume = volume;\n\t}\n\n\tasync setMuted(muted: boolean): Promise<void> {\n\t\tthis.player.muted = muted;\n\t}\n\n\tasync setPlaybackRate(playbackRate: number): Promise<void> {\n\t\tthis.player.playbackRate = playbackRate;\n\t}\n\n\tasync getDuration(): Promise<number> {\n\t\treturn this.player.duration;\n\t}\n\n\tasync getCurrentTime(): Promise<number> {\n\t\treturn this.player.currentTime;\n\t}\n\n\tasync getVolume(): Promise<number> {\n\t\treturn this.player.volume;\n\t}\n\n\tasync getMuted(): Promise<boolean> {\n\t\treturn this.player.muted;\n\t}\n\n\tasync getPlaybackRate(): Promise<number> {\n\t\treturn this.player.playbackRate;\n\t}\n}\n","import { PlayerControllerImpl } from '@/controllers/PlayerControllerImpl';\n\nconst events = [\n\t'apiready',\n\t'seeked',\n\t'video_end',\n\t'durationchange',\n\t'pause',\n\t'playing',\n\t'error',\n] satisfies DM.EventType[];\n\nexport class DailymotionPlayerController extends PlayerControllerImpl<DM.player> {\n\tprivate handlePlayerEvents = (e: { type: DM.EventType }): void => {\n\t\tswitch (e.type) {\n\t\t\tcase 'apiready':\n\t\t\t\tthis.options?.onLoaded?.({ id: this.player.video.videoId });\n\t\t\t\tbreak;\n\t\t\tcase 'seeked':\n\t\t\t\tthis.options?.onTimeUpdate?.({\n\t\t\t\t\tduration: this.player.duration,\n\t\t\t\t\tpercent: this.player.currentTime / this.player.duration,\n\t\t\t\t\tseconds: this.player.currentTime,\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase 'video_end':\n\t\t\t\tthis.options?.onEnded?.();\n\t\t\t\tbreak;\n\t\t\tcase 'durationchange':\n\t\t\t\tbreak;\n\t\t\tcase 'pause':\n\t\t\t\tthis.options?.onPause?.();\n\t\t\t\tbreak;\n\t\t\tcase 'playing':\n\t\t\t\tthis.options?.onPlay?.();\n\t\t\t\tbreak;\n\t\t\tcase 'error':\n\t\t\t\tthis.options?.onError?.(e);\n\t\t\t\tbreak;\n\t\t}\n\t};\n\n\tasync attach(_id: string): Promise<void> {\n\t\tfor (const event of events) {\n\t\t\tthis.player.addEventListener(event, this.handlePlayerEvents);\n\t\t}\n\t}\n\n\tasync detach(): Promise<void> {\n\t\tfor (const event of events) {\n\t\t\tthis.player.removeEventListener(event, this.handlePlayerEvents);\n\t\t}\n\t}\n\n\tasync loadVideo(id: string): Promise<void> {\n\t\tthis.player.load(id);\n\t}\n\n\tasync play(): Promise<void> {\n\t\tthis.player.play();\n\t}\n\n\tasync pause(): Promise<void> {\n\t\tthis.player.pause();\n\t}\n\n\tasync setCurrentTime(seconds: number): Promise<void> {\n\t\tthis.player.seek(seconds);\n\t}\n\n\tasync setVolume(volume: number): Promise<void> {\n\t\tthis.player.setVolume(volume);\n\t}\n\n\tasync setMuted(muted: boolean): Promise<void> {\n\t\tthis.player.setMuted(muted);\n\t}\n\n\tsetPlaybackRate = undefined;\n\n\tasync getDuration(): Promise<number> {\n\t\treturn this.player.duration;\n\t}\n\n\tasync getCurrentTime(): Promise<number> {\n\t\treturn this.player.currentTime;\n\t}\n\n\tasync getVolume(): Promise<number> {\n\t\treturn this.player.volume;\n\t}\n\n\tasync getMuted(): Promise<boolean> {\n\t\treturn this.player.muted;\n\t}\n\n\tgetPlaybackRate = undefined;\n}\n","import { LogLevel } from '@/controllers/Logger';\nimport { PlayerControllerImpl } from '@/controllers/PlayerControllerImpl';\n\ndeclare global {\n\tinterface Window {\n\t\tonNicoPlayerFactoryReady: (callback: nico.NicoPlayerFactory) => void;\n\t}\n}\n\nenum PlayerStatus {\n\tPlay = 2,\n\tPause = 3,\n\tEnd = 4,\n}\n\n// https://github.com/VocaDB/vocadb/blob/a4b5f9d8186772d7e6f58f997bbcbb51509d2539/VocaDbWeb/Scripts/ViewModels/PVs/PVPlayerNico.ts.\nexport class NiconicoPlayerController extends PlayerControllerImpl<HTMLIFrameElement> {\n\tprivate static readonly origin = 'https://embed.nicovideo.jp';\n\n\tprivate duration = 0;\n\tprivate currentTime = 0;\n\tprivate volume = 0;\n\tprivate muted = false;\n\n\tprivate handleMessage = (e: nico.PlayerEvent): void => {\n\t\tif (e.origin !== NiconicoPlayerController.origin) return;\n\n\t\tconst data = e.data;\n\n\t\tswitch (data.eventName) {\n\t\t\tcase 'playerStatusChange':\n\t\t\t\tthis.logger.log(\n\t\t\t\t\tLogLevel.Debug,\n\t\t\t\t\t`player status changed: ${\n\t\t\t\t\t\tPlayerStatus[data.data.playerStatus] ??\n\t\t\t\t\t\tdata.data.playerStatus\n\t\t\t\t\t}`,\n\t\t\t\t);\n\t\t\t\tbreak;\n\n\t\t\tcase 'statusChange':\n\t\t\t\tthis.logger.log(\n\t\t\t\t\tLogLevel.Debug,\n\t\t\t\t\t`status changed: ${\n\t\t\t\t\t\tPlayerStatus[data.data.playerStatus] ??\n\t\t\t\t\t\tdata.data.playerStatus\n\t\t\t\t\t}`,\n\t\t\t\t);\n\n\t\t\t\tswitch (data.data.playerStatus) {\n\t\t\t\t\tcase PlayerStatus.Play:\n\t\t\t\t\t\tthis.options?.onPlay?.();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase PlayerStatus.Pause:\n\t\t\t\t\t\tthis.options?.onPause?.();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase PlayerStatus.End:\n\t\t\t\t\t\tthis.options?.onEnded?.();\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase 'playerMetadataChange':\n\t\t\t\tif (data.data.duration !== undefined)\n\t\t\t\t\tthis.duration = data.data.duration / 1000;\n\n\t\t\t\tthis.currentTime =\n\t\t\t\t\tdata.data.currentTime === undefined\n\t\t\t\t\t\t? 0\n\t\t\t\t\t\t: data.data.currentTime / 1000;\n\n\t\t\t\tthis.volume = data.data.volume;\n\t\t\t\tthis.muted = data.data.muted;\n\n\t\t\t\tthis.options?.onTimeUpdate?.({\n\t\t\t\t\tduration: this.duration,\n\t\t\t\t\tpercent:\n\t\t\t\t\t\tthis.currentTime !== 0 && this.duration !== 0\n\t\t\t\t\t\t\t? this.currentTime / this.duration\n\t\t\t\t\t\t\t: 0,\n\t\t\t\t\tseconds: this.currentTime,\n\t\t\t\t});\n\t\t\t\tbreak;\n\n\t\t\tcase 'loadComplete':\n\t\t\t\tthis.logger.log(LogLevel.Debug, 'load completed');\n\n\t\t\t\tthis.duration = data.data.videoInfo.lengthInSeconds;\n\n\t\t\t\tthis.options?.onLoaded?.({ id: data.data.videoInfo.watchId });\n\t\t\t\tbreak;\n\n\t\t\tcase 'error':\n\t\t\t\t// TODO: Implement.\n\n\t\t\t\tthis.options?.onError?.(data);\n\t\t\t\tbreak;\n\n\t\t\tcase 'player-error:video:play':\n\t\t\tcase 'player-error:video:seek':\n\t\t\t\tthis.options?.onError?.(data);\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tthis.logger.log(\n\t\t\t\t\tLogLevel.Debug,\n\t\t\t\t\t'message',\n\t\t\t\t\t(data as any).eventName,\n\t\t\t\t\t(data as any).data,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t}\n\t};\n\n\tasync attach(): Promise<void> {\n\t\twindow.addEventListener('message', this.handleMessage);\n\t}\n\n\tasync detach(): Promise<void> {\n\t\twindow.removeEventListener('message', this.handleMessage);\n\t}\n\n\tasync loadVideo(id: string): Promise<void> {\n\t\treturn new Promise((resolve, _reject /* TODO: Reject. */) => {\n\t\t\tthis.duration = 0;\n\t\t\tthis.currentTime = 0;\n\t\t\tthis.volume = 0;\n\t\t\tthis.muted = false;\n\n\t\t\t// Wait for iframe to load.\n\t\t\tthis.player.onload = (): void => {\n\t\t\t\tthis.player.onload = null;\n\t\t\t\tresolve();\n\t\t\t};\n\n\t\t\tthis.player.src = `https://embed.nicovideo.jp/watch/${id}?jsapi=1&playerId=1`;\n\t\t});\n\t}\n\n\t// https://blog.hayu.io/web/create/nicovideo-embed-player-api/.\n\tprivate postMessage(message: any): void {\n\t\tthis.player.contentWindow?.postMessage(\n\t\t\t{\n\t\t\t\t...message,\n\t\t\t\tplayerId: '1' /* Needs to be a string, not a number. */,\n\t\t\t\tsourceConnectorType: 1,\n\t\t\t},\n\t\t\tNiconicoPlayerController.origin,\n\t\t);\n\t}\n\n\tasync play(): Promise<void> {\n\t\tthis.postMessage({ eventName: 'play' });\n\t}\n\n\tasync pause(): Promise<void> {\n\t\tthis.postMessage({ eventName: 'pause' });\n\t}\n\n\tasync setCurrentTime(seconds: number): Promise<void> {\n\t\tthis.postMessage({ eventName: 'seek', data: { time: seconds * 1000 } });\n\t}\n\n\tasync setVolume(volume: number): Promise<void> {\n\t\tthis.postMessage({\n\t\t\teventName: 'volumeChange',\n\t\t\tdata: { volume: volume },\n\t\t});\n\t}\n\n\tasync setMuted(muted: boolean): Promise<void> {\n\t\tthis.postMessage({\n\t\t\teventName: 'mute',\n\t\t\tdata: { mute: muted },\n\t\t});\n\t}\n\n\tsetPlaybackRate = undefined;\n\n\tasync getDuration(): Promise<number> {\n\t\treturn this.duration;\n\t}\n\n\tasync getCurrentTime(): Promise<number> {\n\t\treturn this.currentTime;\n\t}\n\n\tasync getVolume(): Promise<number> {\n\t\treturn this.volume;\n\t}\n\n\tasync getMuted(): Promise<boolean> {\n\t\treturn this.muted;\n\t}\n\n\tgetPlaybackRate = undefined;\n}\n","import { PlayerControllerImpl } from '@/controllers/PlayerControllerImpl';\n\n// https://github.com/VocaDB/vocadb/blob/e147650a8f1f85c8fa865d0ab562126c278527ec/VocaDbWeb/Scripts/ViewModels/PVs/PVPlayerSoundCloud.ts.\nexport class SoundCloudPlayerController extends PlayerControllerImpl<SC.SoundCloudWidget> {\n\tprivate getDurationCore(): Promise<number> {\n\t\treturn new Promise((resolve, _reject /* TODO: Reject. */) => {\n\t\t\tthis.player.getDuration(resolve);\n\t\t});\n\t}\n\n\tattach(id: string): Promise<void> {\n\t\treturn new Promise((resolve, _reject /* TODO: reject */) => {\n\t\t\tthis.player.bind(SC.Widget.Events.READY, () => {\n\t\t\t\tthis.player.bind(\n\t\t\t\t\tSC.Widget.Events.PLAY_PROGRESS,\n\t\t\t\t\tasync (event) => {\n\t\t\t\t\t\tconst duration = await this.getDurationCore();\n\n\t\t\t\t\t\tthis.options?.onTimeUpdate?.({\n\t\t\t\t\t\t\tduration: duration / 1000,\n\t\t\t\t\t\t\tpercent: event.currentPosition / duration,\n\t\t\t\t\t\t\tseconds: event.currentPosition / 1000,\n\t\t\t\t\t\t});\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tthis.player.bind(SC.Widget.Events.ERROR, (event) =>\n\t\t\t\t\tthis.options?.onError?.(event),\n\t\t\t\t);\n\t\t\t\tthis.player.bind(SC.Widget.Events.PLAY, () =>\n\t\t\t\t\tthis.options?.onPlay?.(),\n\t\t\t\t);\n\t\t\t\tthis.player.bind(SC.Widget.Events.PAUSE, () =>\n\t\t\t\t\tthis.options?.onPause?.(),\n\t\t\t\t);\n\t\t\t\tthis.player.bind(SC.Widget.Events.FINISH, () =>\n\t\t\t\t\tthis.options?.onEnded?.(),\n\t\t\t\t);\n\n\t\t\t\tthis.options?.onLoaded?.({ id: id });\n\t\t\t\tresolve();\n\t\t\t});\n\t\t});\n\t}\n\n\tasync detach(): Promise<void> {\n\t\tthis.player.unbind(SC.Widget.Events.READY);\n\t\tthis.player.unbind(SC.Widget.Events.PLAY_PROGRESS);\n\t\tthis.player.unbind(SC.Widget.Events.ERROR);\n\t\tthis.player.unbind(SC.Widget.Events.PLAY);\n\t\tthis.player.unbind(SC.Widget.Events.PAUSE);\n\t\tthis.player.unbind(SC.Widget.Events.FINISH);\n\t}\n\n\tprivate static playerLoadAsync(\n\t\tplayer: SC.SoundCloudWidget,\n\t\turl: string,\n\t\toptions: Omit<SC.SoundCloudLoadOptions, 'callback'>,\n\t): Promise<void> {\n\t\treturn new Promise((resolve, _reject /* TODO: Reject. */) => {\n\t\t\tplayer.load(url, { ...options, callback: resolve });\n\t\t});\n\t}\n\n\tasync loadVideo(id: string): Promise<void> {\n\t\tawait SoundCloudPlayerController.playerLoadAsync(this.player, id, {\n\t\t\tauto_play: true,\n\t\t});\n\n\t\tthis.options?.onLoaded?.({ id: id });\n\t}\n\n\tasync play(): Promise<void> {\n\t\tthis.player.play();\n\t}\n\n\tasync pause(): Promise<void> {\n\t\tthis.player.pause();\n\t}\n\n\tasync setCurrentTime(seconds: number): Promise<void> {\n\t\tthis.player.seekTo(seconds * 1000);\n\t}\n\n\tasync setVolume(volume: number): Promise<void> {\n\t\tthis.player.setVolume(volume * 100);\n\t}\n\n\tsetMuted = undefined;\n\n\tsetPlaybackRate = undefined;\n\n\tasync getDuration(): Promise<number> {\n\t\tconst duration = await this.getDurationCore();\n\t\treturn duration / 1000;\n\t}\n\n\tprivate getCurrentTimeCore(): Promise<number> {\n\t\treturn new Promise((resolve, _reject /* TODO: Reject. */) => {\n\t\t\tthis.player.getPosition(resolve);\n\t\t});\n\t}\n\n\tasync getCurrentTime(): Promise<number> {\n\t\tconst position = await this.getCurrentTimeCore();\n\t\treturn position / 1000;\n\t}\n\n\tprivate getVolumeCore(): Promise<number> {\n\t\treturn new Promise((resolve, _reject /* TODO: Reject. */) => {\n\t\t\tthis.player.getVolume(resolve);\n\t\t});\n\t}\n\n\tasync getVolume(): Promise<number> {\n\t\tconst volume = await this.getVolumeCore();\n\t\treturn volume / 100;\n\t}\n\n\tgetMuted = undefined;\n\n\tgetPlaybackRate = undefined;\n}\n","import { PlayerControllerImpl } from '@/controllers/PlayerControllerImpl';\n\nexport class TwitchPlayerController extends PlayerControllerImpl<Twitch.Player> {\n\tprivate handleReady = (): void => {\n\t\tthis.options?.onLoaded?.({ id: this.player.getVideo() });\n\t};\n\n\tprivate handlePlay = (): void => {\n\t\tthis.options?.onPlay?.();\n\t};\n\n\tprivate handlePause = (): void => {\n\t\tthis.options?.onPause?.();\n\t};\n\n\tprivate handleEnded = (): void => {\n\t\tthis.options?.onEnded?.();\n\t};\n\n\tprivate handleSeek = (): void => {\n\t\tthis.options?.onTimeUpdate?.({\n\t\t\tduration: 0,\n\t\t\tpercent: 0,\n\t\t\tseconds: 0,\n\t\t});\n\t};\n\n\tasync attach(_id: string): Promise<void> {\n\t\tthis.player.addEventListener(Twitch.Player.READY, this.handleReady);\n\t\tthis.player.addEventListener(Twitch.Player.PLAYING, this.handlePlay);\n\t\tthis.player.addEventListener(Twitch.Player.PAUSE, this.handlePause);\n\t\tthis.player.addEventListener(Twitch.Player.ENDED, this.handleEnded);\n\t\tthis.player.addEventListener(Twitch.Player.SEEK, this.handleSeek);\n\t}\n\n\tasync detach(): Promise<void> {}\n\n\tasync loadVideo(id: string): Promise<void> {\n\t\tthis.player.setVideo(id, 0);\n\t}\n\n\tasync play(): Promise<void> {\n\t\tthis.player.play();\n\t}\n\n\tasync pause(): Promise<void> {\n\t\tthis.player.pause();\n\t}\n\n\tasync setCurrentTime(seconds: number): Promise<void> {\n\t\tthis.player.seek(seconds);\n\t}\n\n\tasync setVolume(volume: number): Promise<void> {\n\t\tthis.player.setVolume(volume);\n\t}\n\n\tasync setMuted(muted: boolean): Promise<void> {\n\t\tthis.player.setMuted(muted);\n\t}\n\n\tsetPlaybackRate = undefined;\n\n\tasync getDuration(): Promise<number> {\n\t\treturn this.player.getDuration();\n\t}\n\n\tasync getCurrentTime(): Promise<number> {\n\t\treturn this.player.getCurrentTime();\n\t}\n\n\tasync getVolume(): Promise<number> {\n\t\treturn this.player.getVolume();\n\t}\n\n\tasync getMuted(): Promise<boolean> {\n\t\treturn this.player.getMuted();\n\t}\n\n\tgetPlaybackRate = undefined;\n}\n","import { PlayerControllerImpl } from '@/controllers/PlayerControllerImpl';\n\n// https://github.com/cookpete/react-player/blob/e3c324bc6845698179d065fa408db515c2296b4b/src/players/Vimeo.js\nexport class VimeoPlayerController extends PlayerControllerImpl<Vimeo.Player> {\n\tasync attach(): Promise<void> {\n\t\tawait this.player.ready();\n\n\t\tthis.player.on('error', (data) => this.options?.onError?.(data));\n\t\tthis.player.on('loaded', (event) =>\n\t\t\tthis.options?.onLoaded?.({ id: event.id.toString() }),\n\t\t);\n\t\tthis.player.on('play', () => this.options?.onPlay?.());\n\t\tthis.player.on('pause', () => this.options?.onPause?.());\n\t\tthis.player.on('ended', () => this.options?.onEnded?.());\n\t\tthis.player.on('timeupdate', (data) => {\n\t\t\tthis.options?.onTimeUpdate?.({\n\t\t\t\tduration: data.duration,\n\t\t\t\tpercent: data.percent,\n\t\t\t\tseconds: data.seconds,\n\t\t\t});\n\t\t});\n\t}\n\n\tasync detach(): Promise<void> {\n\t\tthis.player.off('error');\n\t\tthis.player.off('loaded');\n\t\tthis.player.off('play');\n\t\tthis.player.off('pause');\n\t\tthis.player.off('ended');\n\t\tthis.player.off('timeupdate');\n\t}\n\n\tasync loadVideo(id: string): Promise<void> {\n\t\tawait this.player.loadVideo(id);\n\t}\n\n\tasync play(): Promise<void> {\n\t\tawait this.player.play();\n\t}\n\n\tasync pause(): Promise<void> {\n\t\tawait this.player.pause();\n\t}\n\n\tasync setCurrentTime(seconds: number): Promise<void> {\n\t\tawait this.player.setCurrentTime(seconds);\n\t}\n\n\tasync setVolume(fraction: number): Promise<void> {\n\t\tawait this.player.setVolume(fraction);\n\t}\n\n\tasync setMuted(muted: boolean): Promise<void> {\n\t\tawait this.player.setMuted(muted);\n\t}\n\n\tasync setPlaybackRate(playbackRate: number): Promise<void> {\n\t\tawait this.player.setPlaybackRate(playbackRate);\n\t}\n\n\tasync getDuration(): Promise<number> {\n\t\treturn this.player.getDuration();\n\t}\n\n\tasync getCurrentTime(): Promise<number> {\n\t\treturn this.player.getCurrentTime();\n\t}\n\n\tasync getVolume(): Promise<number> {\n\t\treturn this.player.getVolume();\n\t}\n\n\tasync getMuted(): Promise<boolean> {\n\t\treturn await this.player.getMuted();\n\t}\n\n\tasync getPlaybackRate(): Promise<number> {\n\t\treturn this.player.getPlaybackRate();\n\t}\n}\n","import { LogLevel } from '@/controllers/Logger';\nimport { PlayerControllerImpl } from '@/controllers/PlayerControllerImpl';\n\ndeclare global {\n\tinterface Window {\n\t\tonYouTubeIframeAPIReady(): void;\n\t}\n}\n\nenum PlayerState {\n\tUNSTARTED = -1,\n\tENDED = 0,\n\tPLAYING = 1,\n\tPAUSED = 2,\n\tBUFFERING = 3,\n\tCUED = 5,\n}\n\n// https://github.com/VocaDB/vocadb/blob/076dac9f0808aba5da7332209fdfd2ff4e12c235/VocaDbWeb/Scripts/ViewModels/PVs/PVPlayerYoutube.ts.\nexport class YouTubePlayerController extends PlayerControllerImpl<YT.Player> {\n\tprivate previousTime?: number;\n\n\tprivate timeUpdateIntervalId?: number;\n\n\tprivate clearTimeUpdateInterval(): void {\n\t\tthis.logger.log(\n\t\t\tLogLevel.Debug,\n\t\t\t'clearTimeUpdateInterval',\n\t\t\tthis.timeUpdateIntervalId,\n\t\t);\n\n\t\twindow.clearInterval(this.timeUpdateIntervalId);\n\n\t\tthis.timeUpdateIntervalId = undefined;\n\t}\n\n\tprivate invokeTimeUpdate(player: YT.Player): void {\n\t\tconst currentTime = player.getCurrentTime();\n\t\tif (currentTime === this.previousTime) return;\n\n\t\tconst duration = player.getDuration();\n\t\tthis.options?.onTimeUpdate?.({\n\t\t\tduration: duration,\n\t\t\tpercent: currentTime / duration,\n\t\t\tseconds: currentTime,\n\t\t});\n\n\t\tthis.previousTime = currentTime;\n\t}\n\n\tprivate setTimeUpdateInterval(): void {\n\t\tthis.logger.log(LogLevel.Debug, 'setTimeUpdateInterval');\n\n\t\tthis.clearTimeUpdateInterval();\n\n\t\tthis.timeUpdateIntervalId = window.setInterval(\n\t\t\t() => this.invokeTimeUpdate(this.player),\n\t\t\t250,\n\t\t);\n\n\t\tthis.logger.log(\n\t\t\tLogLevel.Debug,\n\t\t\t'timeUpdateIntervalId',\n\t\t\tthis.timeUpdateIntervalId,\n\t\t);\n\n\t\tthis.invokeTimeUpdate(this.player);\n\t}\n\n\tattach(id: string): Promise<void> {\n\t\treturn new Promise((resolve, _reject /* TODO: reject */) => {\n\t\t\tthis.player.addEventListener('onReady', async () => {\n\t\t\t\tthis.player.addEventListener('onError', (event) =>\n\t\t\t\t\tthis.options?.onError?.(event.data),\n\t\t\t\t);\n\t\t\t\tthis.player.addEventListener(\n\t\t\t\t\t'onStateChange',\n\t\t\t\t\t(event: YT.EventArgs): void => {\n\t\t\t\t\t\tthis.logger.log(\n\t\t\t\t\t\t\tLogLevel.Debug,\n\t\t\t\t\t\t\t`state changed: ${PlayerState[event.data]}`,\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tswitch (event.data) {\n\t\t\t\t\t\t\tcase YT.PlayerState.CUED:\n\t\t\t\t\t\t\t\tthis.options?.onLoaded?.({ id: id });\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase YT.PlayerState.PLAYING:\n\t\t\t\t\t\t\t\tthis.options?.onPlay?.();\n\t\t\t\t\t\t\t\tthis.setTimeUpdateInterval();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase YT.PlayerState.PAUSED:\n\t\t\t\t\t\t\t\tthis.options?.onPause?.();\n\t\t\t\t\t\t\t\tthis.clearTimeUpdateInterval();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase YT.PlayerState.ENDED:\n\t\t\t\t\t\t\t\tthis.options?.onEnded?.();\n\t\t\t\t\t\t\t\tthis.clearTimeUpdateInterval();\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\t\tawait this.loadVideo(id);\n\t\t\t\tresolve();\n\t\t\t});\n\t\t});\n\t}\n\n\tasync detach(): Promise<void> {\n\t\tthis.clearTimeUpdateInterval();\n\t}\n\n\tasync loadVideo(id: string): Promise<void> {\n\t\tthis.previousTime = undefined;\n\t\tthis.player.cueVideoById(id);\n\t}\n\n\tasync play(): Promise<void> {\n\t\tthis.player.playVideo();\n\t}\n\n\tasync pause(): Promise<void> {\n\t\tthis.player.pauseVideo();\n\t}\n\n\tasync setCurrentTime(seconds: number): Promise<void> {\n\t\tthis.player.seekTo(seconds);\n\n\t\tthis.invokeTimeUpdate(this.player);\n\t}\n\n\tasync setVolume(volume: number): Promise<void> {\n\t\tthis.player.setVolume(volume * 100);\n\t}\n\n\tasync setMuted(muted: boolean): Promise<void> {\n\t\tif (muted) {\n\t\t\tthis.player.mute();\n\t\t} else {\n\t\t\tthis.player.unMute();\n\t\t}\n\t}\n\n\tasync setPlaybackRate(playbackRate: number): Promise<void> {\n\t\tthis.player.setPlaybackRate(playbackRate);\n\t}\n\n\tasync getDuration(): Promise<number> {\n\t\treturn this.player.getDuration();\n\t}\n\n\tasync getCurrentTime(): Promise<number> {\n\t\treturn this.player.getCurrentTime();\n\t}\n\n\tasync getVolume(): Promise<number> {\n\t\treturn this.player.getVolume() / 100;\n\t}\n\n\tasync getMuted(): Promise<boolean> {\n\t\treturn this.player.isMuted();\n\t}\n\n\tasync getPlaybackRate(): Promise<number> {\n\t\treturn this.player.getPlaybackRate();\n\t}\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.es.js","names":["#options","#handleControllerChange","#render"],"sources":["../src/components/NostalgicDivaProvider.tsx","../src/services/VideoService.ts","../src/services/AudioVideoService.ts","../src/services/DailymotionVideoService.ts","../src/services/NiconicoVideoService.ts","../src/services/SoundCloudVideoService.ts","../src/services/SpotifyVideoService.ts","../src/services/TwitchVideoService.ts","../src/services/VimeoVideoService.ts","../src/services/YouTubeVideoService.ts","../src/services/findVideoService.ts","../src/components/NostalgicDiva.tsx","../src/components/defineNostalgicDiva.tsx","../src/controllers/AudioPlayerController.ts","../src/controllers/DailymotionPlayerController.ts","../src/controllers/NiconicoPlayerController.ts","../src/controllers/SoundCloudPlayerController.ts","../src/controllers/SpotifyPlayerController.ts","../src/controllers/TwitchPlayerController.ts","../src/controllers/VimeoPlayerController.ts","../src/controllers/YouTubePlayerController.ts"],"sourcesContent":["import { type ILogger, LogLevel, defaultLogger } from '@/controllers/Logger';\nimport { nullPlayerController } from '@/controllers/NullPlayerController';\nimport type {\n\tIPlayerCommands,\n\tIPlayerController,\n} from '@/controllers/PlayerController';\nimport {\n\ttype ReactElement,\n\ttype ReactNode,\n\tcreateContext,\n\tuseCallback,\n\tuseContext,\n\tuseMemo,\n\tuseRef,\n} from 'react';\n\ninterface NostalgicDivaContextProps extends IPlayerController {\n\tlogger: ILogger;\n\thandleControllerChange: (value: IPlayerController) => void;\n}\n\nconst NostalgicDivaContext = createContext<NostalgicDivaContextProps>(\n\tundefined!,\n);\n\nexport interface NostalgicDivaProviderProps {\n\tchildren?: ReactNode;\n\tlogger?: ILogger;\n}\n\nexport const NostalgicDivaProvider = ({\n\tchildren,\n\tlogger = defaultLogger,\n}: NostalgicDivaProviderProps): ReactElement => {\n\tconst controllerRef = useRef<IPlayerController>(nullPlayerController);\n\n\tconst handleControllerChange = useCallback(\n\t\t(value: IPlayerController): void => {\n\t\t\tlogger.log(\n\t\t\t\tLogLevel.Debug,\n\t\t\t\t'NostalgicDivaProvider.handleControllerChange',\n\t\t\t\tcontrollerRef.current,\n\t\t\t\tvalue,\n\t\t\t);\n\n\t\t\tcontrollerRef.current = value;\n\t\t},\n\t\t[logger],\n\t);\n\n\tconst loadVideo = useCallback(\n\t\tasync (id: string): Promise<void> => {\n\t\t\tlogger.log(\n\t\t\t\tLogLevel.Debug,\n\t\t\t\t'NostalgicDivaProvider.loadVideo',\n\t\t\t\tcontrollerRef.current,\n\t\t\t);\n\n\t\t\tawait controllerRef.current.loadVideo(id);\n\t\t},\n\t\t[logger],\n\t);\n\n\tconst play = useCallback(async (): Promise<void> => {\n\t\tlogger.log(\n\t\t\tLogLevel.Debug,\n\t\t\t'NostalgicDivaProvider.play',\n\t\t\tcontrollerRef.current,\n\t\t);\n\n\t\tawait controllerRef.current.play();\n\t}, [logger]);\n\n\tconst pause = useCallback(async (): Promise<void> => {\n\t\tlogger.log(\n\t\t\tLogLevel.Debug,\n\t\t\t'NostalgicDivaProvider.pause',\n\t\t\tcontrollerRef.current,\n\t\t);\n\n\t\tawait controllerRef.current.pause();\n\t}, [logger]);\n\n\tconst setCurrentTime = useCallback(\n\t\tasync (seconds: number): Promise<void> => {\n\t\t\tlogger.log(\n\t\t\t\tLogLevel.Debug,\n\t\t\t\t'NostalgicDivaProvider.setCurrentTime',\n\t\t\t\tcontrollerRef.current,\n\t\t\t);\n\n\t\t\tawait controllerRef.current.setCurrentTime(seconds);\n\t\t\tawait controllerRef.current.play();\n\t\t},\n\t\t[logger],\n\t);\n\n\tconst setVolume = useCallback(\n\t\tasync (volume: number): Promise<void> => {\n\t\t\tlogger.log(\n\t\t\t\tLogLevel.Debug,\n\t\t\t\t'NostalgicDivaProvider.setVolume',\n\t\t\t\tcontrollerRef.current,\n\t\t\t);\n\n\t\t\tawait controllerRef.current.setVolume(volume);\n\t\t},\n\t\t[logger],\n\t);\n\n\tconst setMuted = useCallback(\n\t\tasync (muted: boolean): Promise<void> => {\n\t\t\tlogger.log(\n\t\t\t\tLogLevel.Debug,\n\t\t\t\t'NostalgicDivaProvider.setMuted',\n\t\t\t\tcontrollerRef.current,\n\t\t\t);\n\n\t\t\tawait controllerRef.current.setMuted(muted);\n\t\t},\n\t\t[logger],\n\t);\n\n\tconst setPlaybackRate = useCallback(\n\t\tasync (playbackRate: number): Promise<void> => {\n\t\t\tlogger.log(\n\t\t\t\tLogLevel.Debug,\n\t\t\t\t'NostalgicDivaProvider.setPlaybackRate',\n\t\t\t\tcontrollerRef.current,\n\t\t\t);\n\n\t\t\tawait controllerRef.current.setPlaybackRate(playbackRate);\n\t\t},\n\t\t[logger],\n\t);\n\n\tconst getDuration = useCallback(async (): Promise<number> => {\n\t\tlogger.log(\n\t\t\tLogLevel.Debug,\n\t\t\t'NostalgicDivaProvider.getDuration',\n\t\t\tcontrollerRef.current,\n\t\t);\n\n\t\treturn await controllerRef.current.getDuration();\n\t}, [logger]);\n\n\tconst getCurrentTime = useCallback(async (): Promise<number> => {\n\t\tlogger.log(\n\t\t\tLogLevel.Debug,\n\t\t\t'NostalgicDivaProvider.getCurrentTime',\n\t\t\tcontrollerRef.current,\n\t\t);\n\n\t\treturn await controllerRef.current.getCurrentTime();\n\t}, [logger]);\n\n\tconst getVolume = useCallback(async (): Promise<number> => {\n\t\tlogger.log(\n\t\t\tLogLevel.Debug,\n\t\t\t'NostalgicDivaProvider.getVolume',\n\t\t\tcontrollerRef.current,\n\t\t);\n\n\t\treturn await controllerRef.current.getVolume();\n\t}, [logger]);\n\n\tconst getMuted = useCallback(async (): Promise<boolean> => {\n\t\tlogger.log(\n\t\t\tLogLevel.Debug,\n\t\t\t'NostalgicDivaProvider.getMuted',\n\t\t\tcontrollerRef.current,\n\t\t);\n\n\t\treturn await controllerRef.current.getMuted();\n\t}, [logger]);\n\n\tconst getPlaybackRate = useCallback(async (): Promise<number> => {\n\t\tlogger.log(\n\t\t\tLogLevel.Debug,\n\t\t\t'NostalgicDivaProvider.getPlaybackRate',\n\t\t\tcontrollerRef.current,\n\t\t);\n\n\t\treturn await controllerRef.current.getPlaybackRate();\n\t}, [logger]);\n\n\tconst supports = useCallback(\n\t\t(command: keyof IPlayerCommands): boolean =>\n\t\t\tcontrollerRef.current.supports(command),\n\t\t[],\n\t);\n\n\tconst value = useMemo(\n\t\t(): NostalgicDivaContextProps => ({\n\t\t\tlogger,\n\t\t\thandleControllerChange,\n\t\t\tloadVideo,\n\t\t\tplay,\n\t\t\tpause,\n\t\t\tsetCurrentTime,\n\t\t\tsetVolume,\n\t\t\tsetMuted,\n\t\t\tsetPlaybackRate,\n\t\t\tgetDuration,\n\t\t\tgetCurrentTime,\n\t\t\tgetVolume,\n\t\t\tgetMuted,\n\t\t\tgetPlaybackRate,\n\t\t\tsupports,\n\t\t}),\n\t\t[\n\t\t\tlogger,\n\t\t\thandleControllerChange,\n\t\t\tloadVideo,\n\t\t\tplay,\n\t\t\tpause,\n\t\t\tsetCurrentTime,\n\t\t\tsetVolume,\n\t\t\tsetMuted,\n\t\t\tsetPlaybackRate,\n\t\t\tgetDuration,\n\t\t\tgetCurrentTime,\n\t\t\tgetVolume,\n\t\t\tgetMuted,\n\t\t\tgetPlaybackRate,\n\t\t\tsupports,\n\t\t],\n\t);\n\n\treturn (\n\t\t<NostalgicDivaContext.Provider value={value}>\n\t\t\t{children}\n\t\t</NostalgicDivaContext.Provider>\n\t);\n};\n\nexport const useNostalgicDiva = (): NostalgicDivaContextProps => {\n\treturn useContext(NostalgicDivaContext);\n};\n","import type { PlayerType } from '@/controllers/PlayerController';\n\nexport abstract class VideoService {\n\tprotected constructor(readonly type: PlayerType) {}\n\n\tabstract canPlay(url: string): boolean;\n\n\tabstract extractVideoId(url: string): string | undefined;\n}\n","import { VideoService } from '@/services/VideoService';\n\n// https://github.com/cookpete/react-player/blob/2811bc59b9368170acc20d4f1e39555413d0d9e1/src/patterns.js\nconst AUDIO_EXTENSIONS =\n\t/\\.(m4a|m4b|mp4a|mpga|mp2|mp2a|mp3|m2a|m3a|wav|weba|aac|oga|spx)($|\\?)/i;\nconst VIDEO_EXTENSIONS = /\\.(mp4|og[gv]|webm|mov|m4v)(#t=[,\\d+]+)?($|\\?)/i;\n\nexport class AudioVideoService extends VideoService {\n\tconstructor() {\n\t\tsuper('Audio');\n\t}\n\n\tcanPlay(url: string): boolean {\n\t\treturn AUDIO_EXTENSIONS.test(url) || VIDEO_EXTENSIONS.test(url);\n\t}\n\n\textractVideoId(url: string): string | undefined {\n\t\treturn url;\n\t}\n}\n","import { VideoService } from '@/services/VideoService';\n\n// https://github.com/cookpete/react-player/blob/2811bc59b9368170acc20d4f1e39555413d0d9e1/src/patterns.js\nconst MATCH_URL_DAILYMOTION =\n\t/^(?:(?:https?):)?(?:\\/\\/)?(?:www\\.)?(?:(?:dailymotion\\.com(?:\\/embed)?\\/video)|dai\\.ly)\\/([a-zA-Z0-9]+)(?:_[\\w_-]+)?(?:[\\w.#_-]+)?/;\n\nexport class DailymotionVideoService extends VideoService {\n\tconstructor() {\n\t\tsuper('Dailymotion');\n\t}\n\n\tcanPlay(url: string): boolean {\n\t\treturn MATCH_URL_DAILYMOTION.test(url);\n\t}\n\n\textractVideoId(url: string): string | undefined {\n\t\tconst matches = MATCH_URL_DAILYMOTION.exec(url);\n\t\treturn matches?.[1];\n\t}\n}\n","import { VideoService } from '@/services/VideoService';\n\nconst MATCH_URL_NICONICO = /(?:www\\.|)?nicovideo\\.jp\\/watch\\/(\\w+)$/;\n\nexport class NiconicoVideoService extends VideoService {\n\tconstructor() {\n\t\tsuper('Niconico');\n\t}\n\n\tcanPlay(url: string): boolean {\n\t\treturn MATCH_URL_NICONICO.test(url);\n\t}\n\n\textractVideoId(url: string): string | undefined {\n\t\tconst matches = MATCH_URL_NICONICO.exec(url);\n\t\treturn matches?.[1];\n\t}\n}\n","import { VideoService } from '@/services/VideoService';\n\n// https://github.com/cookpete/react-player/blob/2811bc59b9368170acc20d4f1e39555413d0d9e1/src/patterns.js\nconst MATCH_URL_SOUNDCLOUD = /(?:soundcloud\\.com|snd\\.sc)\\/[^.]+$/;\n\nexport class SoundCloudVideoService extends VideoService {\n\tconstructor() {\n\t\tsuper('SoundCloud');\n\t}\n\n\tcanPlay(url: string): boolean {\n\t\treturn MATCH_URL_SOUNDCLOUD.test(url);\n\t}\n\n\textractVideoId(url: string): string | undefined {\n\t\treturn url;\n\t}\n}\n","import { VideoService } from '@/services/VideoService';\n\n// Matches `https://open.spotify.com/track/<id>` (with an optional `intl-xx`\n// locale segment and query string) as well as bare `spotify:track:<id>` URIs.\nconst SPOTIFY_TYPES = 'track|episode|album|playlist|show|artist';\nconst MATCH_URL_SPOTIFY = new RegExp(\n\t`^https?://open\\\\.spotify\\\\.com/(?:intl-[a-z]{2}/)?(${SPOTIFY_TYPES})/([a-zA-Z0-9]+)`,\n);\nconst MATCH_URI_SPOTIFY = new RegExp(\n\t`^spotify:(${SPOTIFY_TYPES}):([a-zA-Z0-9]+)$`,\n);\n\nexport class SpotifyVideoService extends VideoService {\n\tconstructor() {\n\t\tsuper('Spotify');\n\t}\n\n\tcanPlay(url: string): boolean {\n\t\treturn MATCH_URL_SPOTIFY.test(url) || MATCH_URI_SPOTIFY.test(url);\n\t}\n\n\t// The Spotify iframe API is driven by Spotify URIs (`spotify:track:<id>`),\n\t// so normalize both URLs and URIs down to that form.\n\textractVideoId(url: string): string | undefined {\n\t\tconst match =\n\t\t\tMATCH_URL_SPOTIFY.exec(url) ?? MATCH_URI_SPOTIFY.exec(url);\n\t\tif (match === null) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst [, type, id] = match;\n\t\treturn `spotify:${type}:${id}`;\n\t}\n}\n","import { VideoService } from '@/services/VideoService';\n\n// https://github.com/cookpete/react-player/blob/2811bc59b9368170acc20d4f1e39555413d0d9e1/src/patterns.js\nconst MATCH_URL_TWITCH_VIDEO = /(?:www\\.|go\\.)?twitch\\.tv\\/videos\\/(\\d+)($|\\?)/;\n\nexport class TwitchVideoService extends VideoService {\n\tconstructor() {\n\t\tsuper('Twitch');\n\t}\n\n\tcanPlay(url: string): boolean {\n\t\treturn MATCH_URL_TWITCH_VIDEO.test(url);\n\t}\n\n\textractVideoId(url: string): string | undefined {\n\t\tconst matches = MATCH_URL_TWITCH_VIDEO.exec(url);\n\t\treturn matches?.[1];\n\t}\n}\n","import { VideoService } from '@/services/VideoService';\n\n// https://github.com/cookpete/react-player/blob/2811bc59b9368170acc20d4f1e39555413d0d9e1/src/patterns.js\nconst MATCH_URL_VIMEO = /vimeo\\.com\\/(\\d+)$/;\n\nexport class VimeoVideoService extends VideoService {\n\tconstructor() {\n\t\tsuper('Vimeo');\n\t}\n\n\tcanPlay(url: string): boolean {\n\t\treturn MATCH_URL_VIMEO.test(url);\n\t}\n\n\textractVideoId(url: string): string | undefined {\n\t\treturn MATCH_URL_VIMEO.exec(url)?.[1];\n\t}\n}\n","import { VideoService } from '@/services/VideoService';\n\n// https://github.com/cookpete/react-player/blob/2811bc59b9368170acc20d4f1e39555413d0d9e1/src/patterns.js\nconst MATCH_URL_YOUTUBE =\n\t/(?:youtu\\.be\\/|youtube(?:-nocookie|education)?\\.com\\/(?:embed\\/|v\\/|watch\\/|watch\\?v=|watch\\?.+&v=|shorts\\/|live\\/))((\\w|-){11})|youtube\\.com\\/playlist\\?list=|youtube\\.com\\/user\\//;\n\nexport class YouTubeVideoService extends VideoService {\n\tconstructor() {\n\t\tsuper('YouTube');\n\t}\n\n\tcanPlay(url: string): boolean {\n\t\treturn MATCH_URL_YOUTUBE.test(url);\n\t}\n\n\textractVideoId(url: string): string | undefined {\n\t\tconst matches = MATCH_URL_YOUTUBE.exec(url);\n\t\treturn matches?.[1];\n\t}\n}\n","import { AudioVideoService } from '@/services/AudioVideoService';\nimport { DailymotionVideoService } from '@/services/DailymotionVideoService';\nimport { NiconicoVideoService } from '@/services/NiconicoVideoService';\nimport { SoundCloudVideoService } from '@/services/SoundCloudVideoService';\nimport { SpotifyVideoService } from '@/services/SpotifyVideoService';\nimport { TwitchVideoService } from '@/services/TwitchVideoService';\nimport type { VideoService } from '@/services/VideoService';\nimport { VimeoVideoService } from '@/services/VimeoVideoService';\nimport { YouTubeVideoService } from '@/services/YouTubeVideoService';\n\nexport const videoServices: VideoService[] = [\n\tnew YouTubeVideoService(),\n\tnew TwitchVideoService(),\n\tnew VimeoVideoService(),\n\tnew DailymotionVideoService(),\n\tnew SoundCloudVideoService(),\n\tnew SpotifyVideoService(),\n\tnew AudioVideoService(),\n\tnew NiconicoVideoService(),\n];\n\nexport function findVideoService(url: string): VideoService | undefined {\n\treturn videoServices.find((videoService) => videoService.canPlay(url));\n}\n","import { useNostalgicDiva } from '@/components/NostalgicDivaProvider';\nimport type { PlayerProps } from '@/components/PlayerContainer';\nimport { LogLevel } from '@/controllers/Logger';\nimport type {\n\tIPlayerController,\n\tPlayerOptions,\n\tPlayerType,\n} from '@/controllers/PlayerController';\nimport { findVideoService } from '@/services/findVideoService';\nimport {\n\ttype ElementType,\n\ttype ReactElement,\n\tSuspense,\n\tlazy,\n\tmemo,\n\tuseCallback,\n} from 'react';\n\nexport const players: Map<PlayerType, ElementType<PlayerProps>> = new Map(\n\tObject.entries({\n\t\tAudio: lazy(() => import('./AudioPlayer')),\n\t\tDailymotion: lazy(() => import('./DailymotionPlayer')),\n\t\tNiconico: lazy(() => import('./NiconicoPlayer')),\n\t\tSoundCloud: lazy(() => import('./SoundCloudPlayer')),\n\t\tSpotify: lazy(() => import('./SpotifyPlayer')),\n\t\tTwitch: lazy(() => import('./TwitchPlayer')),\n\t\tVimeo: lazy(() => import('./VimeoPlayer')),\n\t\tYouTube: lazy(() => import('./YouTubePlayer')),\n\t}),\n);\n\nexport interface NostalgicDivaProps {\n\tsrc: string;\n\toptions?: PlayerOptions;\n\tonControllerChange?: (value: IPlayerController) => void;\n}\n\nfunction getTypeAndVideoId(\n\turl: string,\n): { type: PlayerType; videoId: string } | undefined {\n\tconst videoService = findVideoService(url);\n\tif (videoService === undefined) {\n\t\treturn undefined;\n\t}\n\n\tconst { type, extractVideoId } = videoService;\n\n\tconst videoId = extractVideoId(url);\n\tif (videoId === undefined) {\n\t\treturn undefined;\n\t}\n\n\treturn { type: type, videoId: videoId };\n}\n\nconst EmptyPlayer = memo((): ReactElement => {\n\treturn (\n\t\t<div style={{ width: '100%', height: '100%' }}>\n\t\t\t<iframe\n\t\t\t\tsrc=\"about:blank\"\n\t\t\t\ttitle=\"about:blank\"\n\t\t\t\tstyle={{\n\t\t\t\t\twidth: '100%',\n\t\t\t\t\theight: '100%',\n\t\t\t\t\tborder: 0,\n\t\t\t\t}}\n\t\t\t/>\n\t\t</div>\n\t);\n});\n\nexport const NostalgicDiva = memo(\n\t({\n\t\tsrc,\n\t\toptions,\n\t\tonControllerChange,\n\t}: NostalgicDivaProps): ReactElement => {\n\t\tconst diva = useNostalgicDiva();\n\n\t\tconst handleControllerChange = useCallback(\n\t\t\t(value: IPlayerController) => {\n\t\t\t\tdiva.handleControllerChange(value);\n\n\t\t\t\tonControllerChange?.(value);\n\t\t\t},\n\t\t\t[diva, onControllerChange],\n\t\t);\n\n\t\tdiva.logger.log(LogLevel.Debug, 'NostalgicDiva');\n\n\t\tconst typeAndVideoId = getTypeAndVideoId(src);\n\t\tif (typeAndVideoId === undefined) {\n\t\t\tdiva.logger.log(\n\t\t\t\tLogLevel.Warning,\n\t\t\t\t`Failed to extract type and videoId from src: \"${src}\". Returning EmptyPlayer.`,\n\t\t\t);\n\t\t\treturn <EmptyPlayer />;\n\t\t}\n\n\t\tconst { type, videoId } = typeAndVideoId;\n\n\t\tconst Player = players.get(type);\n\t\tif (Player === undefined) {\n\t\t\tdiva.logger.log(\n\t\t\t\tLogLevel.Warning,\n\t\t\t\t`No player found for type \"${type}\" (videoId: \"${videoId}\"). Returning EmptyPlayer.`,\n\t\t\t);\n\t\t\treturn <EmptyPlayer />;\n\t\t}\n\n\t\treturn (\n\t\t\t<Suspense fallback={null}>\n\t\t\t\t<Player\n\t\t\t\t\tlogger={diva.logger}\n\t\t\t\t\ttype={type}\n\t\t\t\t\tonControllerChange={handleControllerChange}\n\t\t\t\t\tvideoId={videoId}\n\t\t\t\t\toptions={options}\n\t\t\t\t/>\n\t\t\t</Suspense>\n\t\t);\n\t},\n);\n","import { NostalgicDiva } from '@/components/NostalgicDiva';\nimport { NostalgicDivaProvider } from '@/components/NostalgicDivaProvider';\nimport { nullPlayerController } from '@/controllers/NullPlayerController';\nimport type {\n\tIPlayerCommands,\n\tIPlayerController,\n\tPlayerOptions,\n} from '@/controllers/PlayerController';\nimport ReactDOM from 'react-dom';\n\nexport class NostalgicDivaElement\n\textends HTMLElement\n\timplements IPlayerController\n{\n\tstatic readonly observedAttributes = ['src'];\n\n\tcontainer: ShadowRoot;\n\tcontroller: IPlayerController = nullPlayerController;\n\n\tconstructor() {\n\t\tsuper();\n\n\t\tthis.container = this.attachShadow({ mode: 'closed' });\n\t}\n\n\tget src(): string {\n\t\treturn this.getAttribute('src') ?? '';\n\t}\n\n\tset src(value: string) {\n\t\tthis.setAttribute('src', value);\n\t}\n\n\treadonly #options: PlayerOptions = {\n\t\tonError: (e) =>\n\t\t\tthis.dispatchEvent(new CustomEvent('error', { detail: e })),\n\t\tonLoaded: (e) =>\n\t\t\tthis.dispatchEvent(new CustomEvent('loaded', { detail: e })),\n\t\tonPlay: () => this.dispatchEvent(new CustomEvent('play')),\n\t\tonPause: () => this.dispatchEvent(new CustomEvent('pause')),\n\t\tonEnded: () => this.dispatchEvent(new CustomEvent('ended')),\n\t\tonTimeUpdate: (e) =>\n\t\t\tthis.dispatchEvent(new CustomEvent('timeupdate', { detail: e })),\n\t};\n\n\t#handleControllerChange = (value: IPlayerController): void => {\n\t\tconsole.debug(\n\t\t\t'[@nostalgic-diva/web-components] handleControllerChange',\n\t\t);\n\n\t\tthis.controller = value;\n\t};\n\n\t#render(): void {\n\t\tReactDOM.render(\n\t\t\t<NostalgicDivaProvider>\n\t\t\t\t<NostalgicDiva\n\t\t\t\t\tsrc={this.src}\n\t\t\t\t\toptions={this.#options}\n\t\t\t\t\tonControllerChange={this.#handleControllerChange}\n\t\t\t\t/>\n\t\t\t</NostalgicDivaProvider>,\n\t\t\tthis.container,\n\t\t);\n\t}\n\n\tconnectedCallback(): void {\n\t\tconsole.debug('[@nostalgic-diva/web-components] connectedCallback');\n\n\t\tthis.#render();\n\t}\n\n\tdisconnectedCallback(): void {\n\t\tconsole.debug('[@nostalgic-diva/web-components] disconnectedCallback');\n\t}\n\n\tattributeChangedCallback(): void {\n\t\tconsole.debug(\n\t\t\t'[@nostalgic-diva/web-components] attributeChangedCallback',\n\t\t);\n\n\t\tthis.#render();\n\t}\n\n\tasync loadVideo(id: string): Promise<void> {\n\t\tawait this.controller.loadVideo(id);\n\t}\n\n\tasync play(): Promise<void> {\n\t\tawait this.controller.play();\n\t}\n\n\tasync pause(): Promise<void> {\n\t\tawait this.controller.pause();\n\t}\n\n\tasync setCurrentTime(seconds: number): Promise<void> {\n\t\tawait this.controller.setCurrentTime(seconds);\n\t}\n\n\tasync setVolume(volume: number): Promise<void> {\n\t\tawait this.controller.setVolume(volume);\n\t}\n\n\tasync setMuted(muted: boolean): Promise<void> {\n\t\tawait this.controller.setMuted(muted);\n\t}\n\n\tasync setPlaybackRate(playbackRate: number): Promise<void> {\n\t\tawait this.controller.setPlaybackRate(playbackRate);\n\t}\n\n\tasync getDuration(): Promise<number> {\n\t\treturn await this.controller.getDuration();\n\t}\n\n\tasync getCurrentTime(): Promise<number> {\n\t\treturn await this.controller.getCurrentTime();\n\t}\n\n\tasync getVolume(): Promise<number> {\n\t\treturn await this.controller.getVolume();\n\t}\n\n\tasync getMuted(): Promise<boolean> {\n\t\treturn await this.controller.getMuted();\n\t}\n\n\tasync getPlaybackRate(): Promise<number> {\n\t\treturn await this.controller.getPlaybackRate();\n\t}\n\n\tsupports(command: keyof IPlayerCommands): boolean {\n\t\treturn this.controller.supports(command);\n\t}\n}\n\nexport function defineNostalgicDiva(): void {\n\tcustomElements.define('nostalgic-diva', NostalgicDivaElement);\n}\n","import { PlayerControllerImpl } from '@/controllers/PlayerControllerImpl';\n\n// https://github.com/VocaDB/vocadb/blob/61b8c54f3eca906a477101dab4fdd9b154be310e/VocaDbWeb/Scripts/ViewModels/PVs/PVPlayerFile.ts.\nexport class AudioPlayerController extends PlayerControllerImpl<HTMLAudioElement> {\n\tasync attach(): Promise<void> {\n\t\tthis.player.onerror = (event): void => this.options?.onError?.(event);\n\t\tthis.player.onloadeddata = (): void =>\n\t\t\tthis.options?.onLoaded?.({ id: this.player.src });\n\t\tthis.player.onplay = (): void => this.options?.onPlay?.();\n\t\tthis.player.onpause = (): void => this.options?.onPause?.();\n\t\tthis.player.onended = (): void => this.options?.onEnded?.();\n\t\tthis.player.ontimeupdate = (): void => {\n\t\t\tthis.options?.onTimeUpdate?.({\n\t\t\t\tduration: this.player.duration,\n\t\t\t\tpercent: this.player.currentTime / this.player.duration,\n\t\t\t\tseconds: this.player.currentTime,\n\t\t\t});\n\t\t};\n\t}\n\n\tasync detach(): Promise<void> {\n\t\tthis.player.onerror = null;\n\t\tthis.player.onloadeddata = null;\n\t\tthis.player.onplay = null;\n\t\tthis.player.onpause = null;\n\t\tthis.player.onended = null;\n\t\tthis.player.ontimeupdate = null;\n\t}\n\n\tasync loadVideo(id: string): Promise<void> {\n\t\tthis.player.src = id;\n\t}\n\n\tasync play(): Promise<void> {\n\t\tawait this.player.play();\n\t}\n\n\tasync pause(): Promise<void> {\n\t\tthis.player.pause();\n\t}\n\n\tasync setCurrentTime(seconds: number): Promise<void> {\n\t\tthis.player.currentTime = seconds;\n\t}\n\n\tasync setVolume(volume: number): Promise<void> {\n\t\tthis.player.volume = volume;\n\t}\n\n\tasync setMuted(muted: boolean): Promise<void> {\n\t\tthis.player.muted = muted;\n\t}\n\n\tasync setPlaybackRate(playbackRate: number): Promise<void> {\n\t\tthis.player.playbackRate = playbackRate;\n\t}\n\n\tasync getDuration(): Promise<number> {\n\t\treturn this.player.duration;\n\t}\n\n\tasync getCurrentTime(): Promise<number> {\n\t\treturn this.player.currentTime;\n\t}\n\n\tasync getVolume(): Promise<number> {\n\t\treturn this.player.volume;\n\t}\n\n\tasync getMuted(): Promise<boolean> {\n\t\treturn this.player.muted;\n\t}\n\n\tasync getPlaybackRate(): Promise<number> {\n\t\treturn this.player.playbackRate;\n\t}\n}\n","import { PlayerControllerImpl } from '@/controllers/PlayerControllerImpl';\n\nconst events = [\n\t'apiready',\n\t'seeked',\n\t'video_end',\n\t'durationchange',\n\t'pause',\n\t'playing',\n\t'error',\n] satisfies DM.EventType[];\n\nexport class DailymotionPlayerController extends PlayerControllerImpl<DM.player> {\n\tprivate handlePlayerEvents = (e: { type: DM.EventType }): void => {\n\t\tswitch (e.type) {\n\t\t\tcase 'apiready':\n\t\t\t\tthis.options?.onLoaded?.({ id: this.player.video.videoId });\n\t\t\t\tbreak;\n\t\t\tcase 'seeked':\n\t\t\t\tthis.options?.onTimeUpdate?.({\n\t\t\t\t\tduration: this.player.duration,\n\t\t\t\t\tpercent: this.player.currentTime / this.player.duration,\n\t\t\t\t\tseconds: this.player.currentTime,\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase 'video_end':\n\t\t\t\tthis.options?.onEnded?.();\n\t\t\t\tbreak;\n\t\t\tcase 'durationchange':\n\t\t\t\tbreak;\n\t\t\tcase 'pause':\n\t\t\t\tthis.options?.onPause?.();\n\t\t\t\tbreak;\n\t\t\tcase 'playing':\n\t\t\t\tthis.options?.onPlay?.();\n\t\t\t\tbreak;\n\t\t\tcase 'error':\n\t\t\t\tthis.options?.onError?.(e);\n\t\t\t\tbreak;\n\t\t}\n\t};\n\n\tasync attach(_id: string): Promise<void> {\n\t\tfor (const event of events) {\n\t\t\tthis.player.addEventListener(event, this.handlePlayerEvents);\n\t\t}\n\t}\n\n\tasync detach(): Promise<void> {\n\t\tfor (const event of events) {\n\t\t\tthis.player.removeEventListener(event, this.handlePlayerEvents);\n\t\t}\n\t}\n\n\tasync loadVideo(id: string): Promise<void> {\n\t\tthis.player.load(id);\n\t}\n\n\tasync play(): Promise<void> {\n\t\tthis.player.play();\n\t}\n\n\tasync pause(): Promise<void> {\n\t\tthis.player.pause();\n\t}\n\n\tasync setCurrentTime(seconds: number): Promise<void> {\n\t\tthis.player.seek(seconds);\n\t}\n\n\tasync setVolume(volume: number): Promise<void> {\n\t\tthis.player.setVolume(volume);\n\t}\n\n\tasync setMuted(muted: boolean): Promise<void> {\n\t\tthis.player.setMuted(muted);\n\t}\n\n\tsetPlaybackRate = undefined;\n\n\tasync getDuration(): Promise<number> {\n\t\treturn this.player.duration;\n\t}\n\n\tasync getCurrentTime(): Promise<number> {\n\t\treturn this.player.currentTime;\n\t}\n\n\tasync getVolume(): Promise<number> {\n\t\treturn this.player.volume;\n\t}\n\n\tasync getMuted(): Promise<boolean> {\n\t\treturn this.player.muted;\n\t}\n\n\tgetPlaybackRate = undefined;\n}\n","import { LogLevel } from '@/controllers/Logger';\nimport { PlayerControllerImpl } from '@/controllers/PlayerControllerImpl';\n\ndeclare global {\n\tinterface Window {\n\t\tonNicoPlayerFactoryReady: (callback: nico.NicoPlayerFactory) => void;\n\t}\n}\n\nenum PlayerStatus {\n\tPlay = 2,\n\tPause = 3,\n\tEnd = 4,\n}\n\n// https://github.com/VocaDB/vocadb/blob/a4b5f9d8186772d7e6f58f997bbcbb51509d2539/VocaDbWeb/Scripts/ViewModels/PVs/PVPlayerNico.ts.\nexport class NiconicoPlayerController extends PlayerControllerImpl<HTMLIFrameElement> {\n\tprivate static readonly origin = 'https://embed.nicovideo.jp';\n\n\tprivate duration = 0;\n\tprivate currentTime = 0;\n\tprivate volume = 0;\n\tprivate muted = false;\n\n\tprivate handleMessage = (e: nico.PlayerEvent): void => {\n\t\tif (e.origin !== NiconicoPlayerController.origin) return;\n\n\t\tconst data = e.data;\n\n\t\tswitch (data.eventName) {\n\t\t\tcase 'playerStatusChange':\n\t\t\t\tthis.logger.log(\n\t\t\t\t\tLogLevel.Debug,\n\t\t\t\t\t`player status changed: ${\n\t\t\t\t\t\tPlayerStatus[data.data.playerStatus] ??\n\t\t\t\t\t\tdata.data.playerStatus\n\t\t\t\t\t}`,\n\t\t\t\t);\n\t\t\t\tbreak;\n\n\t\t\tcase 'statusChange':\n\t\t\t\tthis.logger.log(\n\t\t\t\t\tLogLevel.Debug,\n\t\t\t\t\t`status changed: ${\n\t\t\t\t\t\tPlayerStatus[data.data.playerStatus] ??\n\t\t\t\t\t\tdata.data.playerStatus\n\t\t\t\t\t}`,\n\t\t\t\t);\n\n\t\t\t\tswitch (data.data.playerStatus) {\n\t\t\t\t\tcase PlayerStatus.Play:\n\t\t\t\t\t\tthis.options?.onPlay?.();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase PlayerStatus.Pause:\n\t\t\t\t\t\tthis.options?.onPause?.();\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase PlayerStatus.End:\n\t\t\t\t\t\tthis.options?.onEnded?.();\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase 'playerMetadataChange':\n\t\t\t\tif (data.data.duration !== undefined)\n\t\t\t\t\tthis.duration = data.data.duration / 1000;\n\n\t\t\t\tthis.currentTime =\n\t\t\t\t\tdata.data.currentTime === undefined\n\t\t\t\t\t\t? 0\n\t\t\t\t\t\t: data.data.currentTime / 1000;\n\n\t\t\t\tthis.volume = data.data.volume;\n\t\t\t\tthis.muted = data.data.muted;\n\n\t\t\t\tthis.options?.onTimeUpdate?.({\n\t\t\t\t\tduration: this.duration,\n\t\t\t\t\tpercent:\n\t\t\t\t\t\tthis.currentTime !== 0 && this.duration !== 0\n\t\t\t\t\t\t\t? this.currentTime / this.duration\n\t\t\t\t\t\t\t: 0,\n\t\t\t\t\tseconds: this.currentTime,\n\t\t\t\t});\n\t\t\t\tbreak;\n\n\t\t\tcase 'loadComplete':\n\t\t\t\tthis.logger.log(LogLevel.Debug, 'load completed');\n\n\t\t\t\tthis.duration = data.data.videoInfo.lengthInSeconds;\n\n\t\t\t\tthis.options?.onLoaded?.({ id: data.data.videoInfo.watchId });\n\t\t\t\tbreak;\n\n\t\t\tcase 'error':\n\t\t\t\t// TODO: Implement.\n\n\t\t\t\tthis.options?.onError?.(data);\n\t\t\t\tbreak;\n\n\t\t\tcase 'player-error:video:play':\n\t\t\tcase 'player-error:video:seek':\n\t\t\t\tthis.options?.onError?.(data);\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tthis.logger.log(\n\t\t\t\t\tLogLevel.Debug,\n\t\t\t\t\t'message',\n\t\t\t\t\t(data as any).eventName,\n\t\t\t\t\t(data as any).data,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t}\n\t};\n\n\tasync attach(): Promise<void> {\n\t\twindow.addEventListener('message', this.handleMessage);\n\t}\n\n\tasync detach(): Promise<void> {\n\t\twindow.removeEventListener('message', this.handleMessage);\n\t}\n\n\tasync loadVideo(id: string): Promise<void> {\n\t\treturn new Promise((resolve, _reject /* TODO: Reject. */) => {\n\t\t\tthis.duration = 0;\n\t\t\tthis.currentTime = 0;\n\t\t\tthis.volume = 0;\n\t\t\tthis.muted = false;\n\n\t\t\t// Wait for iframe to load.\n\t\t\tthis.player.onload = (): void => {\n\t\t\t\tthis.player.onload = null;\n\t\t\t\tresolve();\n\t\t\t};\n\n\t\t\tthis.player.src = `https://embed.nicovideo.jp/watch/${id}?jsapi=1&playerId=1`;\n\t\t});\n\t}\n\n\t// https://blog.hayu.io/web/create/nicovideo-embed-player-api/.\n\tprivate postMessage(message: any): void {\n\t\tthis.player.contentWindow?.postMessage(\n\t\t\t{\n\t\t\t\t...message,\n\t\t\t\tplayerId: '1' /* Needs to be a string, not a number. */,\n\t\t\t\tsourceConnectorType: 1,\n\t\t\t},\n\t\t\tNiconicoPlayerController.origin,\n\t\t);\n\t}\n\n\tasync play(): Promise<void> {\n\t\tthis.postMessage({ eventName: 'play' });\n\t}\n\n\tasync pause(): Promise<void> {\n\t\tthis.postMessage({ eventName: 'pause' });\n\t}\n\n\tasync setCurrentTime(seconds: number): Promise<void> {\n\t\tthis.postMessage({ eventName: 'seek', data: { time: seconds * 1000 } });\n\t}\n\n\tasync setVolume(volume: number): Promise<void> {\n\t\tthis.postMessage({\n\t\t\teventName: 'volumeChange',\n\t\t\tdata: { volume: volume },\n\t\t});\n\t}\n\n\tasync setMuted(muted: boolean): Promise<void> {\n\t\tthis.postMessage({\n\t\t\teventName: 'mute',\n\t\t\tdata: { mute: muted },\n\t\t});\n\t}\n\n\tsetPlaybackRate = undefined;\n\n\tasync getDuration(): Promise<number> {\n\t\treturn this.duration;\n\t}\n\n\tasync getCurrentTime(): Promise<number> {\n\t\treturn this.currentTime;\n\t}\n\n\tasync getVolume(): Promise<number> {\n\t\treturn this.volume;\n\t}\n\n\tasync getMuted(): Promise<boolean> {\n\t\treturn this.muted;\n\t}\n\n\tgetPlaybackRate = undefined;\n}\n","import { PlayerControllerImpl } from '@/controllers/PlayerControllerImpl';\n\n// https://github.com/VocaDB/vocadb/blob/e147650a8f1f85c8fa865d0ab562126c278527ec/VocaDbWeb/Scripts/ViewModels/PVs/PVPlayerSoundCloud.ts.\nexport class SoundCloudPlayerController extends PlayerControllerImpl<SC.SoundCloudWidget> {\n\tprivate getDurationCore(): Promise<number> {\n\t\treturn new Promise((resolve, _reject /* TODO: Reject. */) => {\n\t\t\tthis.player.getDuration(resolve);\n\t\t});\n\t}\n\n\tattach(id: string): Promise<void> {\n\t\treturn new Promise((resolve, _reject /* TODO: reject */) => {\n\t\t\tthis.player.bind(SC.Widget.Events.READY, () => {\n\t\t\t\tthis.player.bind(\n\t\t\t\t\tSC.Widget.Events.PLAY_PROGRESS,\n\t\t\t\t\tasync (event) => {\n\t\t\t\t\t\tconst duration = await this.getDurationCore();\n\n\t\t\t\t\t\tthis.options?.onTimeUpdate?.({\n\t\t\t\t\t\t\tduration: duration / 1000,\n\t\t\t\t\t\t\tpercent: event.currentPosition / duration,\n\t\t\t\t\t\t\tseconds: event.currentPosition / 1000,\n\t\t\t\t\t\t});\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tthis.player.bind(SC.Widget.Events.ERROR, (event) =>\n\t\t\t\t\tthis.options?.onError?.(event),\n\t\t\t\t);\n\t\t\t\tthis.player.bind(SC.Widget.Events.PLAY, () =>\n\t\t\t\t\tthis.options?.onPlay?.(),\n\t\t\t\t);\n\t\t\t\tthis.player.bind(SC.Widget.Events.PAUSE, () =>\n\t\t\t\t\tthis.options?.onPause?.(),\n\t\t\t\t);\n\t\t\t\tthis.player.bind(SC.Widget.Events.FINISH, () =>\n\t\t\t\t\tthis.options?.onEnded?.(),\n\t\t\t\t);\n\n\t\t\t\tthis.options?.onLoaded?.({ id: id });\n\t\t\t\tresolve();\n\t\t\t});\n\t\t});\n\t}\n\n\tasync detach(): Promise<void> {\n\t\tthis.player.unbind(SC.Widget.Events.READY);\n\t\tthis.player.unbind(SC.Widget.Events.PLAY_PROGRESS);\n\t\tthis.player.unbind(SC.Widget.Events.ERROR);\n\t\tthis.player.unbind(SC.Widget.Events.PLAY);\n\t\tthis.player.unbind(SC.Widget.Events.PAUSE);\n\t\tthis.player.unbind(SC.Widget.Events.FINISH);\n\t}\n\n\tprivate static playerLoadAsync(\n\t\tplayer: SC.SoundCloudWidget,\n\t\turl: string,\n\t\toptions: Omit<SC.SoundCloudLoadOptions, 'callback'>,\n\t): Promise<void> {\n\t\treturn new Promise((resolve, _reject /* TODO: Reject. */) => {\n\t\t\tplayer.load(url, { ...options, callback: resolve });\n\t\t});\n\t}\n\n\tasync loadVideo(id: string): Promise<void> {\n\t\tawait SoundCloudPlayerController.playerLoadAsync(this.player, id, {\n\t\t\tauto_play: true,\n\t\t});\n\n\t\tthis.options?.onLoaded?.({ id: id });\n\t}\n\n\tasync play(): Promise<void> {\n\t\tthis.player.play();\n\t}\n\n\tasync pause(): Promise<void> {\n\t\tthis.player.pause();\n\t}\n\n\tasync setCurrentTime(seconds: number): Promise<void> {\n\t\tthis.player.seekTo(seconds * 1000);\n\t}\n\n\tasync setVolume(volume: number): Promise<void> {\n\t\tthis.player.setVolume(volume * 100);\n\t}\n\n\tsetMuted = undefined;\n\n\tsetPlaybackRate = undefined;\n\n\tasync getDuration(): Promise<number> {\n\t\tconst duration = await this.getDurationCore();\n\t\treturn duration / 1000;\n\t}\n\n\tprivate getCurrentTimeCore(): Promise<number> {\n\t\treturn new Promise((resolve, _reject /* TODO: Reject. */) => {\n\t\t\tthis.player.getPosition(resolve);\n\t\t});\n\t}\n\n\tasync getCurrentTime(): Promise<number> {\n\t\tconst position = await this.getCurrentTimeCore();\n\t\treturn position / 1000;\n\t}\n\n\tprivate getVolumeCore(): Promise<number> {\n\t\treturn new Promise((resolve, _reject /* TODO: Reject. */) => {\n\t\t\tthis.player.getVolume(resolve);\n\t\t});\n\t}\n\n\tasync getVolume(): Promise<number> {\n\t\tconst volume = await this.getVolumeCore();\n\t\treturn volume / 100;\n\t}\n\n\tgetMuted = undefined;\n\n\tgetPlaybackRate = undefined;\n}\n","import { PlayerControllerImpl } from '@/controllers/PlayerControllerImpl';\n\n// https://developer.spotify.com/documentation/embeds/references/iframe-api\nexport class SpotifyPlayerController extends PlayerControllerImpl<Spotify.EmbedController> {\n\t// The Spotify iframe API has no getters for the duration or the current\n\t// position, so cache the latest values reported by `playback_update` (both\n\t// in milliseconds).\n\tprivate duration = 0;\n\tprivate position = 0;\n\n\t// Spotify has no dedicated play/pause events, so derive them from `isPaused`\n\t// transitions in `playback_update`.\n\tprivate previousIsPaused = true;\n\n\t// Spotify has no `ended` event and reports the end of a track repeatedly,\n\t// including after the next track has been requested. Track the URI the embed\n\t// is currently playing so a stale end update (still tagged with the previous\n\t// track) cannot fire `onEnded` again and skip the next track.\n\tprivate currentUri: string | undefined;\n\tprivate ended = false;\n\n\tprivate handlePlaybackUpdate = (e: {\n\t\tdata: Spotify.PlaybackUpdateData;\n\t}): void => {\n\t\tconst { position, duration, isPaused, playingURI } = e.data;\n\n\t\t// A different URI means the embed has moved on to another track, so any\n\t\t// pending end state from the previous track no longer applies.\n\t\tif (playingURI !== this.currentUri) {\n\t\t\tthis.currentUri = playingURI;\n\t\t\tthis.ended = false;\n\t\t}\n\n\t\tthis.position = position;\n\t\tthis.duration = duration;\n\n\t\tthis.options?.onTimeUpdate?.({\n\t\t\tduration: duration / 1000,\n\t\t\tpercent: duration > 0 ? position / duration : 0,\n\t\t\tseconds: position / 1000,\n\t\t});\n\n\t\tif (isPaused !== this.previousIsPaused) {\n\t\t\tthis.previousIsPaused = isPaused;\n\n\t\t\tif (isPaused) {\n\t\t\t\tthis.options?.onPause?.();\n\t\t\t} else {\n\t\t\t\tthis.options?.onPlay?.();\n\t\t\t}\n\t\t}\n\n\t\t// Spotify has no `ended` event. When a track finishes, `position` reaches\n\t\t// `duration` (with `isPaused` staying false) and updates then stop, so\n\t\t// emit `onEnded` once at that point. Reset when playback moves back from\n\t\t// the end (e.g. repeat-one, which restarts the track) so it can fire\n\t\t// again on the next playthrough.\n\t\tif (duration > 0 && position >= duration) {\n\t\t\tif (!this.ended) {\n\t\t\t\tthis.ended = true;\n\t\t\t\tthis.options?.onEnded?.();\n\t\t\t}\n\t\t} else {\n\t\t\tthis.ended = false;\n\t\t}\n\t};\n\n\tasync attach(id: string): Promise<void> {\n\t\t// Fire `onLoaded` only once the embed is `ready`. The host app autoplays\n\t\t// by calling `play` from its `onLoaded` handler, and the embed silently\n\t\t// drops playback commands issued before it is ready.\n\t\tthis.player.addListener('ready', () =>\n\t\t\tthis.options?.onLoaded?.({ id: id }),\n\t\t);\n\t\tthis.player.addListener('playback_update', this.handlePlaybackUpdate);\n\t}\n\n\tasync detach(): Promise<void> {\n\t\t// `removeListener` is unreliable in the Spotify iframe API, but the\n\t\t// embed (and thus its listeners) is torn down when React unmounts the\n\t\t// host element, so there is nothing to clean up here.\n\t}\n\n\tasync loadVideo(id: string): Promise<void> {\n\t\tthis.duration = 0;\n\t\tthis.position = 0;\n\t\tthis.previousIsPaused = true;\n\t\t// `ended` is intentionally not reset here: the previous track's final\n\t\t// update can still arrive after this call, and resetting would let it\n\t\t// fire `onEnded` again. It is reset once the embed reports the new URI.\n\n\t\tthis.player.loadUri(id);\n\n\t\tthis.options?.onLoaded?.({ id: id });\n\t}\n\n\tasync play(): Promise<void> {\n\t\t// `resume` both starts and resumes playback, unlike `play`.\n\t\tthis.player.resume();\n\t}\n\n\tasync pause(): Promise<void> {\n\t\tthis.player.pause();\n\t}\n\n\tasync setCurrentTime(seconds: number): Promise<void> {\n\t\t// The Spotify embed ignores `seek(0)`, so use the dedicated `restart`\n\t\t// method to return to the beginning of the track.\n\t\tif (seconds <= 0) {\n\t\t\tthis.player.restart();\n\t\t} else {\n\t\t\tthis.player.seek(seconds);\n\t\t}\n\t}\n\n\tsetVolume = undefined;\n\n\tsetMuted = undefined;\n\n\tsetPlaybackRate = undefined;\n\n\tasync getDuration(): Promise<number> {\n\t\treturn this.duration / 1000;\n\t}\n\n\tasync getCurrentTime(): Promise<number> {\n\t\treturn this.position / 1000;\n\t}\n\n\tgetVolume = undefined;\n\n\tgetMuted = undefined;\n\n\tgetPlaybackRate = undefined;\n}\n","import { PlayerControllerImpl } from '@/controllers/PlayerControllerImpl';\n\nexport class TwitchPlayerController extends PlayerControllerImpl<Twitch.Player> {\n\tprivate handleReady = (): void => {\n\t\tthis.options?.onLoaded?.({ id: this.player.getVideo() });\n\t};\n\n\tprivate handlePlay = (): void => {\n\t\tthis.options?.onPlay?.();\n\t};\n\n\tprivate handlePause = (): void => {\n\t\tthis.options?.onPause?.();\n\t};\n\n\tprivate handleEnded = (): void => {\n\t\tthis.options?.onEnded?.();\n\t};\n\n\tprivate handleSeek = (): void => {\n\t\tthis.options?.onTimeUpdate?.({\n\t\t\tduration: 0,\n\t\t\tpercent: 0,\n\t\t\tseconds: 0,\n\t\t});\n\t};\n\n\tasync attach(_id: string): Promise<void> {\n\t\tthis.player.addEventListener(Twitch.Player.READY, this.handleReady);\n\t\tthis.player.addEventListener(Twitch.Player.PLAYING, this.handlePlay);\n\t\tthis.player.addEventListener(Twitch.Player.PAUSE, this.handlePause);\n\t\tthis.player.addEventListener(Twitch.Player.ENDED, this.handleEnded);\n\t\tthis.player.addEventListener(Twitch.Player.SEEK, this.handleSeek);\n\t}\n\n\tasync detach(): Promise<void> {}\n\n\tasync loadVideo(id: string): Promise<void> {\n\t\tthis.player.setVideo(id, 0);\n\t}\n\n\tasync play(): Promise<void> {\n\t\tthis.player.play();\n\t}\n\n\tasync pause(): Promise<void> {\n\t\tthis.player.pause();\n\t}\n\n\tasync setCurrentTime(seconds: number): Promise<void> {\n\t\tthis.player.seek(seconds);\n\t}\n\n\tasync setVolume(volume: number): Promise<void> {\n\t\tthis.player.setVolume(volume);\n\t}\n\n\tasync setMuted(muted: boolean): Promise<void> {\n\t\tthis.player.setMuted(muted);\n\t}\n\n\tsetPlaybackRate = undefined;\n\n\tasync getDuration(): Promise<number> {\n\t\treturn this.player.getDuration();\n\t}\n\n\tasync getCurrentTime(): Promise<number> {\n\t\treturn this.player.getCurrentTime();\n\t}\n\n\tasync getVolume(): Promise<number> {\n\t\treturn this.player.getVolume();\n\t}\n\n\tasync getMuted(): Promise<boolean> {\n\t\treturn this.player.getMuted();\n\t}\n\n\tgetPlaybackRate = undefined;\n}\n","import { PlayerControllerImpl } from '@/controllers/PlayerControllerImpl';\n\n// https://github.com/cookpete/react-player/blob/e3c324bc6845698179d065fa408db515c2296b4b/src/players/Vimeo.js\nexport class VimeoPlayerController extends PlayerControllerImpl<Vimeo.Player> {\n\tasync attach(): Promise<void> {\n\t\tawait this.player.ready();\n\n\t\tthis.player.on('error', (data) => this.options?.onError?.(data));\n\t\tthis.player.on('loaded', (event) =>\n\t\t\tthis.options?.onLoaded?.({ id: event.id.toString() }),\n\t\t);\n\t\tthis.player.on('play', () => this.options?.onPlay?.());\n\t\tthis.player.on('pause', () => this.options?.onPause?.());\n\t\tthis.player.on('ended', () => this.options?.onEnded?.());\n\t\tthis.player.on('timeupdate', (data) => {\n\t\t\tthis.options?.onTimeUpdate?.({\n\t\t\t\tduration: data.duration,\n\t\t\t\tpercent: data.percent,\n\t\t\t\tseconds: data.seconds,\n\t\t\t});\n\t\t});\n\t}\n\n\tasync detach(): Promise<void> {\n\t\tthis.player.off('error');\n\t\tthis.player.off('loaded');\n\t\tthis.player.off('play');\n\t\tthis.player.off('pause');\n\t\tthis.player.off('ended');\n\t\tthis.player.off('timeupdate');\n\t}\n\n\tasync loadVideo(id: string): Promise<void> {\n\t\tawait this.player.loadVideo(id);\n\t}\n\n\tasync play(): Promise<void> {\n\t\tawait this.player.play();\n\t}\n\n\tasync pause(): Promise<void> {\n\t\tawait this.player.pause();\n\t}\n\n\tasync setCurrentTime(seconds: number): Promise<void> {\n\t\tawait this.player.setCurrentTime(seconds);\n\t}\n\n\tasync setVolume(fraction: number): Promise<void> {\n\t\tawait this.player.setVolume(fraction);\n\t}\n\n\tasync setMuted(muted: boolean): Promise<void> {\n\t\tawait this.player.setMuted(muted);\n\t}\n\n\tasync setPlaybackRate(playbackRate: number): Promise<void> {\n\t\tawait this.player.setPlaybackRate(playbackRate);\n\t}\n\n\tasync getDuration(): Promise<number> {\n\t\treturn this.player.getDuration();\n\t}\n\n\tasync getCurrentTime(): Promise<number> {\n\t\treturn this.player.getCurrentTime();\n\t}\n\n\tasync getVolume(): Promise<number> {\n\t\treturn this.player.getVolume();\n\t}\n\n\tasync getMuted(): Promise<boolean> {\n\t\treturn await this.player.getMuted();\n\t}\n\n\tasync getPlaybackRate(): Promise<number> {\n\t\treturn this.player.getPlaybackRate();\n\t}\n}\n","import { LogLevel } from '@/controllers/Logger';\nimport { PlayerControllerImpl } from '@/controllers/PlayerControllerImpl';\n\ndeclare global {\n\tinterface Window {\n\t\tonYouTubeIframeAPIReady(): void;\n\t}\n}\n\nenum PlayerState {\n\tUNSTARTED = -1,\n\tENDED = 0,\n\tPLAYING = 1,\n\tPAUSED = 2,\n\tBUFFERING = 3,\n\tCUED = 5,\n}\n\n// https://github.com/VocaDB/vocadb/blob/076dac9f0808aba5da7332209fdfd2ff4e12c235/VocaDbWeb/Scripts/ViewModels/PVs/PVPlayerYoutube.ts.\nexport class YouTubePlayerController extends PlayerControllerImpl<YT.Player> {\n\tprivate previousTime?: number;\n\n\tprivate timeUpdateIntervalId?: number;\n\n\tprivate clearTimeUpdateInterval(): void {\n\t\tthis.logger.log(\n\t\t\tLogLevel.Debug,\n\t\t\t'clearTimeUpdateInterval',\n\t\t\tthis.timeUpdateIntervalId,\n\t\t);\n\n\t\twindow.clearInterval(this.timeUpdateIntervalId);\n\n\t\tthis.timeUpdateIntervalId = undefined;\n\t}\n\n\tprivate invokeTimeUpdate(player: YT.Player): void {\n\t\tconst currentTime = player.getCurrentTime();\n\t\tif (currentTime === this.previousTime) return;\n\n\t\tconst duration = player.getDuration();\n\t\tthis.options?.onTimeUpdate?.({\n\t\t\tduration: duration,\n\t\t\tpercent: currentTime / duration,\n\t\t\tseconds: currentTime,\n\t\t});\n\n\t\tthis.previousTime = currentTime;\n\t}\n\n\tprivate setTimeUpdateInterval(): void {\n\t\tthis.logger.log(LogLevel.Debug, 'setTimeUpdateInterval');\n\n\t\tthis.clearTimeUpdateInterval();\n\n\t\tthis.timeUpdateIntervalId = window.setInterval(\n\t\t\t() => this.invokeTimeUpdate(this.player),\n\t\t\t250,\n\t\t);\n\n\t\tthis.logger.log(\n\t\t\tLogLevel.Debug,\n\t\t\t'timeUpdateIntervalId',\n\t\t\tthis.timeUpdateIntervalId,\n\t\t);\n\n\t\tthis.invokeTimeUpdate(this.player);\n\t}\n\n\tattach(id: string): Promise<void> {\n\t\treturn new Promise((resolve, _reject /* TODO: reject */) => {\n\t\t\tthis.player.addEventListener('onReady', async () => {\n\t\t\t\tthis.player.addEventListener('onError', (event) =>\n\t\t\t\t\tthis.options?.onError?.(event.data),\n\t\t\t\t);\n\t\t\t\tthis.player.addEventListener(\n\t\t\t\t\t'onStateChange',\n\t\t\t\t\t(event: YT.EventArgs): void => {\n\t\t\t\t\t\tthis.logger.log(\n\t\t\t\t\t\t\tLogLevel.Debug,\n\t\t\t\t\t\t\t`state changed: ${PlayerState[event.data]}`,\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tswitch (event.data) {\n\t\t\t\t\t\t\tcase YT.PlayerState.CUED:\n\t\t\t\t\t\t\t\tthis.options?.onLoaded?.({ id: id });\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase YT.PlayerState.PLAYING:\n\t\t\t\t\t\t\t\tthis.options?.onPlay?.();\n\t\t\t\t\t\t\t\tthis.setTimeUpdateInterval();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase YT.PlayerState.PAUSED:\n\t\t\t\t\t\t\t\tthis.options?.onPause?.();\n\t\t\t\t\t\t\t\tthis.clearTimeUpdateInterval();\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase YT.PlayerState.ENDED:\n\t\t\t\t\t\t\t\tthis.options?.onEnded?.();\n\t\t\t\t\t\t\t\tthis.clearTimeUpdateInterval();\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\t\tawait this.loadVideo(id);\n\t\t\t\tresolve();\n\t\t\t});\n\t\t});\n\t}\n\n\tasync detach(): Promise<void> {\n\t\tthis.clearTimeUpdateInterval();\n\t}\n\n\tasync loadVideo(id: string): Promise<void> {\n\t\tthis.previousTime = undefined;\n\t\tthis.player.cueVideoById(id);\n\t}\n\n\tasync play(): Promise<void> {\n\t\tthis.player.playVideo();\n\t}\n\n\tasync pause(): Promise<void> {\n\t\tthis.player.pauseVideo();\n\t}\n\n\tasync setCurrentTime(seconds: number): Promise<void> {\n\t\tthis.player.seekTo(seconds);\n\n\t\tthis.invokeTimeUpdate(this.player);\n\t}\n\n\tasync setVolume(volume: number): Promise<void> {\n\t\tthis.player.setVolume(volume * 100);\n\t}\n\n\tasync setMuted(muted: boolean): Promise<void> {\n\t\tif (muted) {\n\t\t\tthis.player.mute();\n\t\t} else {\n\t\t\tthis.player.unMute();\n\t\t}\n\t}\n\n\tasync setPlaybackRate(playbackRate: number): Promise<void> {\n\t\tthis.player.setPlaybackRate(playbackRate);\n\t}\n\n\tasync getDuration(): Promise<number> {\n\t\treturn this.player.getDuration();\n\t}\n\n\tasync getCurrentTime(): Promise<number> {\n\t\treturn this.player.getCurrentTime();\n\t}\n\n\tasync getVolume(): Promise<number> {\n\t\treturn this.player.getVolume() / 100;\n\t}\n\n\tasync getMuted(): Promise<boolean> {\n\t\treturn this.player.isMuted();\n\t}\n\n\tasync getPlaybackRate(): Promise<number> {\n\t\treturn this.player.getPlaybackRate();\n\t}\n}\n"],"mappings":"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"}
|