@tidal-music/player
Version:
Player logic for TIDAL
225 lines (224 loc) • 7.12 kB
JavaScript
import { e as W, B as M, a as x, x as O } from "./index-C6ZwgBzI.js";
import { g as V } from "./_commonjsHelpers-DaMA6jEr.js";
var w, P;
function q() {
return P || (P = 1, w = /* @__PURE__ */ function() {
function n(e, t, a, i, s) {
return e < t || a < t ? e > a ? a + 1 : e + 1 : i === s ? t : t + 1;
}
return function(e, t) {
if (e === t)
return 0;
if (e.length > t.length) {
var a = e;
e = t, t = a;
}
for (var i = e.length, s = t.length; i > 0 && e.charCodeAt(i - 1) === t.charCodeAt(s - 1); )
i--, s--;
for (var c = 0; c < i && e.charCodeAt(c) === t.charCodeAt(c); )
c++;
if (i -= c, s -= c, i === 0 || s < 3)
return s;
var o = 0, r, u, h, d, m, l, f, p, D, I, E, L, v = [];
for (r = 0; r < i; r++)
v.push(r + 1), v.push(e.charCodeAt(c + r));
for (var A = v.length - 1; o < s - 3; )
for (D = t.charCodeAt(c + (u = o)), I = t.charCodeAt(c + (h = o + 1)), E = t.charCodeAt(c + (d = o + 2)), L = t.charCodeAt(c + (m = o + 3)), l = o += 4, r = 0; r < A; r += 2)
f = v[r], p = v[r + 1], u = n(f, u, h, D, p), h = n(u, h, d, I, p), d = n(h, d, m, E, p), l = n(d, m, l, L, p), v[r] = l, m = d, d = h, h = u, u = f;
for (; o < s; )
for (D = t.charCodeAt(c + (u = o)), l = ++o, r = 0; r < A; r += 2)
f = v[r], v[r] = l = n(f, u, l, D, v[r + 1]), u = f;
return l;
};
}()), w;
}
var B = q();
const N = /* @__PURE__ */ V(B);
function U(n) {
return new CustomEvent("device-change", {
detail: {
devices: n
}
});
}
const g = M.parse(navigator.userAgent);
class b {
controllableVolume;
id;
name;
nativeDeviceId;
type;
webDeviceId;
constructor({
controllableVolume: e,
name: t,
nativeDeviceId: a,
type: i,
webDeviceId: s
}) {
this.name = t, this.id = a === "default" && s === "default" ? "default" : O(), this.nativeDeviceId = a, this.webDeviceId = s, this.type = i, this.controllableVolume = e !== !1;
}
}
function y(n) {
if (j(n))
return "windowsCommunication";
if ("id" in n && n.id === "BuiltInSpeakerDevice")
return "builtIn";
if ("type" in n && n.type === "airplay")
return "airplay";
if ("label" in n) {
const e = n.label.toLowerCase();
if (e.includes("bluetooth"))
return "bluetooth";
if (e.includes("displayport"))
return "displayPort";
if (e.includes("hdmi"))
return "hdmi";
if (e.includes("usb"))
return "usb";
if (e.includes("built-in"))
return "builtIn";
if (e.includes("airplay"))
return "airplay";
}
}
function C(n, e) {
const t = e.toLowerCase();
let a = n;
return t.includes("mac") && (a = (n.split("(")[0] ?? "").trim()), a;
}
function j(n) {
let e;
return "label" in n && (e = n.label), "name" in n && (e = n.name), e?.startsWith("Communications") ?? !1;
}
function S(n, e) {
if (e = C(e, g.os.name || ""), [...n].length === 0 || e === "")
return;
const t = [...n].find((i) => i.name === e);
if (t)
return t;
const a = [...n].filter((i) => e.includes(i.name) || i.name.includes(e)).map((i) => ({
device: i,
distance: N(i.name, e)
})).sort((i, s) => i.distance - s.distance).reverse();
if (a.length > 0) {
const i = a.pop();
if (i && i.distance <= 16)
return i.device;
}
}
class T {
#i;
#n;
#a = "shared";
#e;
#t;
#s;
outputDevices;
constructor() {
this.#t = /* @__PURE__ */ new Set(), this.#s = /* @__PURE__ */ new Set(), this.#e = new EventTarget(), this.#n = new b({
name: "System Default",
nativeDeviceId: "default",
type: "systemDefault",
webDeviceId: "default"
}), this.#i = this.#n, this.outputDevices = /* @__PURE__ */ new Set([this.#n]), this.hydrateWebDevices().then().catch(console.error), navigator.mediaDevices.addEventListener("devicechange", () => {
this.hydrateWebDevices().then().catch(console.error);
}), this.#e.addEventListener("native-devices", (e) => {
this.#t = new Set(e.detail), this.queueUpdate().then().catch(console.error);
}), this.#e.addEventListener("web-devices", (e) => {
this.#s = new Set(e.detail), this.queueUpdate().then().catch(console.error);
});
}
addNativeDevices(e) {
this.#e.dispatchEvent(
new CustomEvent("native-devices", {
detail: e
})
);
}
addWebDevices(e) {
e = e.filter((t) => t.deviceId !== "default"), this.#e.dispatchEvent(
new CustomEvent("web-devices", {
detail: e
})
);
}
emitDeviceChange() {
W.dispatchEvent(U([...this.outputDevices]));
}
getNativeDevice(e) {
return [...this.#t].find((t) => t.id === e);
}
async hydrateWebDevices() {
const t = (await navigator.mediaDevices.enumerateDevices()).filter((a) => a.kind === "audiooutput");
this.addWebDevices(t);
}
mergeDevices() {
[...this.outputDevices].filter((e) => e.id !== "default").forEach((e) => {
e.nativeDeviceId = void 0, e.webDeviceId = void 0;
}), this.#t.forEach((e) => {
const t = S(this.outputDevices, e.name);
t ? (t.nativeDeviceId = e.id, t.controllableVolume = e.controllableVolume, t.type = y(e) || t.type) : this.outputDevices.add(
new b({
controllableVolume: e.controllableVolume,
name: C(e.name, g.os.name || ""),
nativeDeviceId: e.id,
type: y(e)
})
);
}), this.#s.forEach((e) => {
const t = S(this.outputDevices, e.label);
t ? (t.webDeviceId = e.deviceId, t.type = y(e) || t.type) : this.outputDevices.add(
new b({
name: C(e.label, g.os.name || ""),
type: y(e),
webDeviceId: e.deviceId
})
);
}), [...this.outputDevices].filter(
(e) => e.webDeviceId === void 0 && e.nativeDeviceId === void 0 || e.type === "airplay" || e.type === "windowsCommunication"
).forEach((e) => this.outputDevices.delete(e));
}
async queueUpdate() {
const e = new Promise(
(i) => this.#e.addEventListener(
"native-devices",
(s) => i(s.detail),
{ once: !0 }
)
), t = new Promise(
(i) => this.#e.addEventListener(
"web-devices",
(s) => i(s.detail),
{ once: !0 }
)
), a = (i) => new Promise((s) => setTimeout(() => s(), i));
await Promise.any([e, t, a(1e3)]), this.mergeDevices(), this.emitDeviceChange();
}
set activeDevice(e) {
this.#i = e, this.#a = "shared", x.activePlayer?.updateOutputDevice()?.catch(console.error);
}
get activeDevice() {
return this.#i;
}
/**
* Set the current device mode for the output device.
*/
set deviceMode(e) {
const { activeDevice: t } = this, { activePlayer: a } = x;
t && a && a.name === "nativePlayer" && this.deviceMode !== e && (this.#a = e, a.updateDeviceMode());
}
get deviceMode() {
return this.#a;
}
}
const F = new T();
export {
b as OutputDevice,
T as OutputDevices,
y as findOutputType,
S as getOutputDeviceByName,
j as isWindowsCommunicationsDevice,
C as marshalLabel,
F as outputDevices
};