2019-03-20 05:56:39 +08:00
|
|
|
import * as mpd from "./mpd.js";
|
|
|
|
import * as parser from "./parser.js";
|
2019-03-22 22:35:04 +08:00
|
|
|
import * as html from "./html.js";
|
2019-03-22 23:17:10 +08:00
|
|
|
import * as conf from "../conf.js";
|
2019-03-20 05:56:39 +08:00
|
|
|
|
|
|
|
let cache = {};
|
2019-03-21 17:53:38 +08:00
|
|
|
const MIME = "image/jpeg";
|
2019-03-22 23:17:10 +08:00
|
|
|
const STORAGE_PREFIX = `art-${conf.artSize}` ;
|
2019-03-21 17:53:38 +08:00
|
|
|
|
|
|
|
function store(key, data) {
|
|
|
|
localStorage.setItem(`${STORAGE_PREFIX}-${key}`, data);
|
|
|
|
}
|
|
|
|
|
|
|
|
function load(key) {
|
|
|
|
return localStorage.getItem(`${STORAGE_PREFIX}-${key}`);
|
|
|
|
}
|
2019-03-20 05:56:39 +08:00
|
|
|
|
|
|
|
async function getImageData(songUrl) {
|
|
|
|
let data = [];
|
|
|
|
let offset = 0;
|
|
|
|
while (1) {
|
|
|
|
let params = ["albumart", `"${mpd.escape(songUrl)}"`, offset];
|
|
|
|
let lines = await mpd.command(params.join(" "));
|
|
|
|
data = data.concat(lines[2]);
|
|
|
|
let metadata = parser.linesToStruct(lines.slice(0, 2));
|
|
|
|
if (data.length >= Number(metadata["size"])) { return data; }
|
|
|
|
offset += Number(metadata["binary"]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function bytesToImage(bytes) {
|
|
|
|
let blob = new Blob([bytes]);
|
2019-03-22 22:35:04 +08:00
|
|
|
let src = URL.createObjectURL(blob);
|
|
|
|
let image = html.node("img", {src});
|
2019-03-20 05:56:39 +08:00
|
|
|
return new Promise(resolve => {
|
|
|
|
image.onload = () => resolve(image);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-03-21 17:53:38 +08:00
|
|
|
function resize(image) {
|
2019-03-22 23:17:10 +08:00
|
|
|
let canvas = html.node("canvas", {width:conf.artSize, height:conf.artSize});
|
2019-03-20 05:56:39 +08:00
|
|
|
let ctx = canvas.getContext("2d");
|
2019-03-22 23:17:10 +08:00
|
|
|
ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
|
2019-03-21 17:53:38 +08:00
|
|
|
return canvas;
|
2019-03-20 05:56:39 +08:00
|
|
|
}
|
|
|
|
|
2019-03-20 23:20:17 +08:00
|
|
|
export async function get(artist, album, songUrl = null) {
|
|
|
|
let key = `${artist}-${album}`;
|
|
|
|
if (key in cache) { return cache[key]; }
|
|
|
|
|
2019-03-21 17:53:38 +08:00
|
|
|
let loaded = await load(key);
|
|
|
|
if (loaded) {
|
|
|
|
cache[key] = loaded;
|
|
|
|
return loaded;
|
|
|
|
}
|
|
|
|
|
2019-03-20 23:20:17 +08:00
|
|
|
if (!songUrl) { return null; }
|
|
|
|
|
|
|
|
// promise to be returned in the meantime
|
|
|
|
let resolve;
|
|
|
|
let promise = new Promise(res => resolve = res);
|
|
|
|
cache[key] = promise;
|
|
|
|
|
|
|
|
try {
|
|
|
|
let data = await getImageData(songUrl);
|
|
|
|
let bytes = new Uint8Array(data);
|
|
|
|
let image = await bytesToImage(bytes);
|
2019-03-21 17:53:38 +08:00
|
|
|
let url = resize(image).toDataURL(MIME);
|
|
|
|
store(key, url);
|
2019-03-20 23:20:17 +08:00
|
|
|
cache[key] = url;
|
|
|
|
resolve(url);
|
|
|
|
} catch (e) {
|
|
|
|
cache[key] = null;
|
|
|
|
}
|
|
|
|
return cache[key];
|
2019-03-20 05:56:39 +08:00
|
|
|
}
|