Added PLS/ASX support

This commit is contained in:
Dustin Brett
2022-06-09 18:44:19 -07:00
parent aa95caa811
commit e70e160d75
9 changed files with 79 additions and 68 deletions

15
components/apps/Webamp/declares.d.ts vendored Normal file
View File

@@ -0,0 +1,15 @@
declare module "playlist-parser" {
type PlaylistTrack = {
artist?: string;
file: string;
length?: number;
title?: string;
};
type Parser = {
parse: (data: string) => PlaylistTrack[];
};
export const ASX: Parser;
export const M3U: Parser;
export const PLS: Parser;
}

View File

@@ -106,20 +106,30 @@ export const parseTrack = async (
};
};
export const m3uToTracks = async (
playlistData: string,
defaultPlaylistName?: string
export const tracksFromPlaylist = async (
data: string,
extension: string,
defaultName?: string
): Promise<Track[]> => {
const parser = await import("iptv-playlist-parser");
const { items = [] } = parser.parse(playlistData) || {};
const { ASX, M3U, PLS } = await import("playlist-parser");
const parser: Record<string, typeof ASX | typeof M3U | typeof PLS> = {
".asx": ASX,
".m3u": M3U,
".pls": PLS,
};
const tracks = parser[extension]?.parse(data) ?? [];
return items.map(({ group: { title }, name, url }) => ({
duration: 0,
metaData: {
album: title || defaultPlaylistName || "",
artist: "",
title: name,
},
url,
}));
return tracks.map(({ artist = "", file, length = 0, title = "" }) => {
const [parsedArtist, parsedTitle] = [artist.trim(), title.trim()];
return {
duration: length > 0 ? length : 0,
metaData: {
album: parsedTitle || defaultName,
artist: parsedArtist,
title: parsedTitle,
},
url: file,
};
});
};

View File

@@ -1,8 +1,8 @@
import {
cleanBufferOnSkinLoad,
focusWindow,
m3uToTracks,
parseTrack,
tracksFromPlaylist,
unFocus,
} from "components/apps/Webamp/functions";
import StyledWebamp from "components/apps/Webamp/StyledWebamp";
@@ -14,6 +14,7 @@ import { useFileSystem } from "contexts/fileSystem";
import { useProcesses } from "contexts/process";
import { basename, extname } from "path";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { AUDIO_PLAYLIST_EXTENSIONS } from "utils/constants";
import { bufferToUrl, loadFiles } from "utils/functions";
import type { Options } from "webamp";
@@ -39,13 +40,14 @@ const Webamp: FC<ComponentProcessProps> = ({ id }) => {
if (url) {
const extension = extname(url).toLowerCase();
if (extension === ".m3u") {
return {
initialTracks: await m3uToTracks(
(await readFile(url)).toString(),
basename(url, extname(url))
),
};
if (AUDIO_PLAYLIST_EXTENSIONS.has(extension)) {
const initialTracks = await tracksFromPlaylist(
(await readFile(url)).toString(),
extension,
basename(url, extname(url))
);
return initialTracks.length > 0 ? { initialTracks } : {};
}
if (extension === ".mp3") {

View File

@@ -3,10 +3,10 @@ import {
cleanBufferOnSkinLoad,
closeEqualizer,
getWebampElement,
m3uToTracks,
MAIN_WINDOW,
parseTrack,
PLAYLIST_WINDOW,
tracksFromPlaylist,
updateWebampPosition,
} from "components/apps/Webamp/functions";
import type { WebampCI } from "components/apps/Webamp/types";
@@ -16,9 +16,13 @@ import useWindowActions from "components/system/Window/Titlebar/useWindowActions
import { useFileSystem } from "contexts/fileSystem";
import { useProcesses } from "contexts/process";
import { useSession } from "contexts/session";
import { extname } from "path";
import { useCallback, useRef } from "react";
import { useTheme } from "styled-components";
import { TRANSITIONS_IN_MILLISECONDS } from "utils/constants";
import {
AUDIO_PLAYLIST_EXTENSIONS,
TRANSITIONS_IN_MILLISECONDS,
} from "utils/constants";
import { haltEvent } from "utils/functions";
import type { Options, Track } from "webamp";
@@ -74,10 +78,13 @@ const useWebamp = (id: string): Webamp => {
);
if (externalUrl) {
if (externalUrl?.endsWith(".m3u")) {
const m3uPlaylist = await fetch(externalUrl);
const playlistExtension = extname(externalUrl).toLowerCase();
return m3uToTracks(await m3uPlaylist.text());
if (AUDIO_PLAYLIST_EXTENSIONS.has(playlistExtension)) {
return tracksFromPlaylist(
await (await fetch(externalUrl)).text(),
playlistExtension
);
}
return [

View File

@@ -106,6 +106,7 @@ const types = {
};
const extensions = {
".asx": types.AudioPlaylist,
".exe": types.Application,
".gen": types.SegaGenesisRom,
".htm": types.HtmlDocument,
@@ -119,6 +120,7 @@ const extensions = {
".mp3": types.Music,
".nes": types.NintendoRom,
".pdf": types.PdfDocument,
".pls": types.AudioPlaylist,
".py": types.PythonFile,
".sfc": types.SuperNintendoRom,
".smc": types.SuperNintendoRom,

View File

@@ -50,10 +50,10 @@
"html-to-image": "^1.9.0",
"idb-keyval": "^6.1.0",
"ini": "^3.0.0",
"iptv-playlist-parser": "^0.11.0",
"isomorphic-git": "^1.17.3",
"music-metadata-browser": "^2.5.6",
"next": "^12.1.6",
"playlist-parser": "^0.0.12",
"prettier": "2.6.2",
"react": "^18.1.0",
"react-dom": "^18.1.0",

View File

@@ -25,7 +25,7 @@ This project is greatly augmented by code from the open source community. Thank
- [fflate](https://github.com/101arrowz/fflate)
- [7z-wasm](https://github.com/use-strict/7z-wasm)
- [music-metadata-browser](https://github.com/Borewit/music-metadata-browser)
- [iptv-playlist-parser](https://github.com/freearhey/iptv-playlist-parser)
- [playlist-parser](https://github.com/nickdesaulniers/javascript-playlist-parser)
- [isomorphic-git](https://github.com/isomorphic-git/isomorphic-git)
- [ini](https://github.com/npm/ini)
- [gif.js](https://github.com/jnordberg/gif.js)

View File

@@ -166,6 +166,8 @@ export const ONE_DAY_IN_MILLISECONDS = 86400000;
export const AUDIO_FILE_EXTENSIONS = new Set([".aac", ".oga", ".wav"]);
export const AUDIO_PLAYLIST_EXTENSIONS = new Set([".asx", ".m3u", ".pls"]);
export const VIDEO_FILE_EXTENSIONS = new Set([
".m4v",
".mkv",

View File

@@ -3325,14 +3325,6 @@ invariant@^2.2.3:
dependencies:
loose-envify "^1.0.0"
iptv-playlist-parser@^0.11.0:
version "0.11.0"
resolved "https://registry.yarnpkg.com/iptv-playlist-parser/-/iptv-playlist-parser-0.11.0.tgz#64f63f1925ca81519d255364150c356700d8dc6e"
integrity sha512-kUqayPVW8WVhDCodEOBzUlPpBTtCR3k7uvIHfmK/xB8TJCOnbMpvaxzHl0W3ImRS9qDVkBtzcIyfutdLXUr2KQ==
dependencies:
is-valid-path "^0.1.1"
valid-url "^1.0.9"
is-arrayish@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
@@ -3379,11 +3371,6 @@ is-date-object@^1.0.1:
dependencies:
has-tostringtag "^1.0.0"
is-extglob@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0"
integrity sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==
is-extglob@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
@@ -3404,13 +3391,6 @@ is-generator-fn@^2.0.0:
resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118"
integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==
is-glob@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863"
integrity sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==
dependencies:
is-extglob "^1.0.0"
is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3:
version "4.0.3"
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
@@ -3418,13 +3398,6 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3:
dependencies:
is-extglob "^2.1.1"
is-invalid-path@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/is-invalid-path/-/is-invalid-path-0.1.0.tgz#307a855b3cf1a938b44ea70d2c61106053714f34"
integrity sha512-aZMG0T3F34mTg4eTdszcGXx54oiZ4NtHSft3hWNJMGJXUUqdIj3cOZuHcU0nCWWcY3jd7yRe/3AEm3vSNTpBGQ==
dependencies:
is-glob "^2.0.0"
is-negative-zero@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150"
@@ -3506,13 +3479,6 @@ is-typedarray@^1.0.0:
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==
is-valid-path@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/is-valid-path/-/is-valid-path-0.1.1.tgz#110f9ff74c37f663e1ec7915eb451f2db93ac9df"
integrity sha512-+kwPrVDu9Ms03L90Qaml+79+6DZHqHyRoANI6IsZJ/g8frhnfchDOBCa0RbQ6/kdHt5CS5OeIEyrYznNuVN+8A==
dependencies:
is-invalid-path "^0.1.0"
is-weakref@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2"
@@ -4905,6 +4871,13 @@ pkg-dir@^4.2.0:
dependencies:
find-up "^4.0.0"
playlist-parser@^0.0.12:
version "0.0.12"
resolved "https://registry.yarnpkg.com/playlist-parser/-/playlist-parser-0.0.12.tgz#4250e5b11771ad68213983bf9bb6ecab64ddf526"
integrity sha512-eMC1F79YUOd4eH5t+e8ejfE93x4/ikUddICAqByAVehAePF1tBBgU03wmUFXXzobgTd1qL46ynsxByUSIKpVLA==
dependencies:
xmldom "0.1.16"
pluralize@^8.0.0:
version "8.0.0"
resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1"
@@ -6273,11 +6246,6 @@ v8-to-istanbul@^9.0.0:
"@types/istanbul-lib-coverage" "^2.0.1"
convert-source-map "^1.6.0"
valid-url@^1.0.9:
version "1.0.9"
resolved "https://registry.yarnpkg.com/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200"
integrity sha1-HBRHm0DxOXp1eC8RXkCGRHQzogA=
validate-npm-package-license@^3.0.1:
version "3.0.4"
resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"
@@ -6497,6 +6465,11 @@ xmlchars@^2.2.0:
resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb"
integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==
xmldom@0.1.16:
version "0.1.16"
resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.16.tgz#cf2602832b1ab5c3e6813fca08fe70196ba15e8c"
integrity sha1-zyYCgysatcPmgT/KCP5wGWuhXow=
xterm-addon-fit@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/xterm-addon-fit/-/xterm-addon-fit-0.2.1.tgz#353f43921eb78e3f9ad3f3afbb14e7ac183ca738"