Skip to content

Commit

Permalink
SongDownloader - Working native metadata tagging
Browse files Browse the repository at this point in the history
  • Loading branch information
Inrixia committed Jun 25, 2024
1 parent 86480c1 commit 10c6e0f
Show file tree
Hide file tree
Showing 9 changed files with 112 additions and 109 deletions.
20 changes: 1 addition & 19 deletions plugins/SongDownloader/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions plugins/SongDownloader/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
{
"dependencies": {
"@inrixia/lib": "../_lib",
"flac-stream-tagger": "^1.0.8"
"@inrixia/lib": "../_lib"
}
}
69 changes: 0 additions & 69 deletions plugins/SongDownloader/src/addMetadata.ts

This file was deleted.

12 changes: 8 additions & 4 deletions plugins/SongDownloader/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { settings } from "./Settings";
import { ContextMenu } from "@inrixia/lib/ContextMenu";
import { PlaybackInfoCache } from "@inrixia/lib/Caches/PlaybackInfoCache";
import { startTrackDownload, openDialog, saveDialog, getDownloadProgress } from "@inrixia/lib/nativeBridge";
import { makeTags } from "./makeTags";
export { Settings } from "./Settings";

type DownloadButtoms = Record<string, HTMLButtonElement>;
Expand Down Expand Up @@ -92,10 +93,11 @@ ContextMenu.onOpen(async (contextSource, contextMenu, trackItems) => {
});
});

const downloadTrack = async (track: TrackItem, updateMethods: ButtonMethods, filePath?: string) => {
const downloadTrack = async (trackItem: TrackItem, updateMethods: ButtonMethods, filePath?: string) => {
const metaTags = makeTags(trackItem);
updateMethods.set("Fetching playback info...");
const playbackInfo = await PlaybackInfoCache.ensure(track.id!, settings.desiredDownloadQuality);
const fileName = parseFileName(track, playbackInfo);
const playbackInfo = await PlaybackInfoCache.ensure(trackItem.id!, settings.desiredDownloadQuality);
const fileName = parseFileName(trackItem, playbackInfo);
if (filePath !== undefined) {
filePath = `${filePath}\\${fileName}`;
} else {
Expand All @@ -104,9 +106,11 @@ const downloadTrack = async (track: TrackItem, updateMethods: ButtonMethods, fil
const dialogResult = await saveDialog({ defaultPath, filters: [{ name: "", extensions: [parseExtension(fileName) ?? "*"] }] });
filePath = dialogResult?.filePath;
}
updateMethods.set("Building metadata...");
await metaTags;
updateMethods.set("Downloading...");
let downloadEnded = false;
const downloadComplete = startTrackDownload(playbackInfo, filePath).finally(() => (downloadEnded = true));
const downloadComplete = startTrackDownload(playbackInfo, filePath, await metaTags).finally(() => (downloadEnded = true));
const updateDownloadProgress = async () => {
const downloadProgress = await getDownloadProgress(filePath);
if (downloadProgress !== undefined) updateMethods.onProgress(downloadProgress);
Expand Down
45 changes: 45 additions & 0 deletions plugins/SongDownloader/src/makeTags.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { utils, actions } from "@neptune";
import { TrackItem } from "neptune-types/tidal";
import { fullTitle } from "@inrixia/lib/fullTitle";
import { interceptPromise } from "@inrixia/lib/intercept/interceptPromise";

import { AlbumCache } from "@inrixia/lib/Caches/AlbumCache";
import { FlacTagMap } from "@inrixia/lib/nativeBridge";

export const makeTags = async (track: TrackItem) => {
const tags: FlacTagMap = {};
if (track.title) tags.title = fullTitle(track);
if (track.album?.title) tags.album = track.album.title;
if (track.trackNumber !== undefined) tags.trackNumber = track.trackNumber.toString();
if (track.releaseDate !== undefined) tags.date = track.releaseDate;
if (track.copyright) tags.copyright = track.copyright;
if (track.isrc) tags.isrc = track.isrc;
if (track.replayGain) tags.REPLAYGAIN_TRACK_GAIN = track.replayGain.toString();
if (track.peak) tags.REPLAYGAIN_TRACK_PEAK = track.peak.toString();
if (track.url) tags.comment = track.url;
if (track.artist?.name) tags.artist = track.artist.name;
tags.performer = (track.artists ?? []).map(({ name }) => name).filter((name) => name !== undefined);

if (track.id !== undefined) {
const lyrics = await interceptPromise(() => actions.content.loadItemLyrics({ itemId: track.id!, itemType: "track" }), ["content/LOAD_ITEM_LYRICS_SUCCESS"], ["content/LOAD_ITEM_LYRICS_FAIL"])
.catch(() => undefined)
.then((res) => res?.[0]);
if (lyrics?.lyrics !== undefined) tags.lyrics = lyrics.lyrics;
}

const albumId = track.album?.id;
let cover = track.album?.cover;
if (albumId !== undefined) {
const album = await AlbumCache.get(albumId);
if (album !== undefined) {
tags.albumArtist = (album.artists ?? []).map(({ name }) => name).filter((name) => name !== undefined);
if (album.genre) tags.genres = album.genre;
if (album.recordLabel) tags.organization = album.recordLabel;
if (album.numberOfTracks) tags.totalTracks = album.numberOfTracks.toString();
if (!tags.date && album.releaseDate) tags.date = album.releaseDate;
if (!tags.date && album.releaseYear) tags.date = album.releaseYear.toString();
cover ??= album.cover;
}
}
return { tags, coverUrl: utils.getMediaURLFromID(cover) };
};
10 changes: 0 additions & 10 deletions plugins/_lib/fetch.ts

This file was deleted.

43 changes: 38 additions & 5 deletions plugins/_lib/nativeBridge/native/downloadTrack.native.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,51 @@
import type { ExtendedPlayackInfo } from "../../Caches/PlaybackInfoTypes";
import type { DownloadProgress } from "./request/helpers.native";
import { type Readable } from "stream";
import { ManifestMimeType, type ExtendedPlayackInfo } from "../../Caches/PlaybackInfoTypes";
import { rejectNotOk, toBuffer, type DownloadProgress } from "./request/helpers.native";
import { requestTrackStream } from "./request/requestTrack.native";
import { createWriteStream } from "fs";

import { FlacStreamTagger, PictureType, type FlacTagMap } from "flac-stream-tagger";
import { requestStream } from "./request/requestStream.native";

export type { DownloadProgress } from "./request/helpers.native";
export type { FlacTagMap } from "flac-stream-tagger";

const downloadStatus: Record<string, DownloadProgress> = {};
export type MetaTags = { tags: FlacTagMap; coverUrl?: string };
const addTags = async (extPlaybackInfo: ExtendedPlayackInfo, stream: Readable, metaTags?: MetaTags) => {
if (metaTags === undefined) return stream;
const { tags, coverUrl } = metaTags;
if (extPlaybackInfo.manifestMimeType === ManifestMimeType.Tidal) {
switch (extPlaybackInfo.manifest.codecs) {
case "flac": {
let picture;
if (coverUrl !== undefined) {
try {
picture = {
pictureType: PictureType.FrontCover,
buffer: await requestStream(coverUrl).then(rejectNotOk).then(toBuffer),
};
} catch {}
}
return stream.pipe(
new FlacStreamTagger({
tagMap: tags,
picture,
})
);
}
}
}
return stream;
};

export const startTrackDownload = async (extPlaybackInfo: ExtendedPlayackInfo, filePath: string): Promise<void> => {
const downloadStatus: Record<string, DownloadProgress> = {};
export const startTrackDownload = async (extPlaybackInfo: ExtendedPlayackInfo, filePath: string, metaTags?: MetaTags): Promise<void> => {
if (downloadStatus[filePath] !== undefined) throw new Error(`Something is already downloading to ${filePath}`);
try {
const stream = await requestTrackStream(extPlaybackInfo, { onProgress: (progress) => (downloadStatus[filePath] = progress) });
const metaStream = await addTags(extPlaybackInfo, stream, metaTags);
return new Promise((res) =>
stream.pipe(createWriteStream(filePath)).on("finish", () => {
metaStream.pipe(createWriteStream(filePath)).on("finish", () => {
delete downloadStatus[filePath];
res();
})
Expand Down
18 changes: 18 additions & 0 deletions plugins/_lib/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions plugins/_lib/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"name": "@inrixia/lib",
"dependencies": {
"flac-stream-tagger": "^1.0.9",
"idb": "^8.0.0",
"music-metadata": "^7.14.0"
}
Expand Down

0 comments on commit 10c6e0f

Please sign in to comment.