summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMinteck <contact@minteck.org>2022-03-27 21:29:24 +0200
committerMinteck <contact@minteck.org>2022-03-27 21:29:24 +0200
commit226516aca48e97d3dc4e4df213bc2023e64b1afd (patch)
tree60fb4f24b75b120e7e5b0e149069b16367c48aa0
downloadargon-226516aca48e97d3dc4e4df213bc2023e64b1afd.tar.gz
argon-226516aca48e97d3dc4e4df213bc2023e64b1afd.tar.bz2
argon-226516aca48e97d3dc4e4df213bc2023e64b1afd.zip
Initial commit
-rw-r--r--.DS_Storebin0 -> 10244 bytes
-rw-r--r--.gitignore4
-rw-r--r--.idea/.gitignore8
-rw-r--r--.idea/Argon.iml8
-rw-r--r--.idea/deployment.xml15
-rw-r--r--.idea/inspectionProfiles/Project_Default.xml6
-rw-r--r--.idea/modules.xml8
-rw-r--r--.idea/php.xml4
-rw-r--r--.idea/sshConfigs.xml8
-rw-r--r--.idea/webServers.xml14
-rw-r--r--_frame/about/index.php228
-rw-r--r--_frame/home/index.php39
-rw-r--r--_frame/index.php4
-rw-r--r--_frame/library.internal/index.php7
-rw-r--r--_frame/library.internal/main.php60
-rw-r--r--_frame/library.internal/view.php161
-rw-r--r--_frame/lyrics/index.php99
-rw-r--r--_frame/settings/index.php51
-rw-r--r--api/count_local_view.php1
-rw-r--r--api/get_app_css.php14
-rw-r--r--api/get_app_js.php14
-rw-r--r--api/get_audio_files.php50
-rw-r--r--api/get_image.php20
-rw-r--r--api/get_list.php141
-rw-r--r--css/fonts.css216
-rw-r--r--css/frame-about.css52
-rw-r--r--css/frame-home.css51
-rw-r--r--css/frame-library.css209
-rw-r--r--css/frame-lyrics.css49
-rw-r--r--css/frame-settings.css15
-rw-r--r--css/frame.css27
-rw-r--r--css/general.css11
-rw-r--r--css/header.css20
-rw-r--r--css/loader.css36
-rw-r--r--css/navigation.css56
-rw-r--r--css/player.css94
-rw-r--r--css/seekbar.css34
-rw-r--r--dark.css62
-rw-r--r--data/.DS_Storebin0 -> 6148 bytes
-rw-r--r--favicon.icobin0 -> 310725 bytes
-rw-r--r--fonts/.DS_Storebin0 -> 6148 bytes
-rw-r--r--fonts/Poppins-Black.eotbin0 -> 158040 bytes
-rw-r--r--fonts/Poppins-Black.ttfbin0 -> 157864 bytes
-rw-r--r--fonts/Poppins-Black.woffbin0 -> 70640 bytes
-rw-r--r--fonts/Poppins-Black.woff2bin0 -> 50660 bytes
-rw-r--r--fonts/Poppins-BlackItalic.eotbin0 -> 178528 bytes
-rw-r--r--fonts/Poppins-BlackItalic.ttfbin0 -> 178340 bytes
-rw-r--r--fonts/Poppins-BlackItalic.woffbin0 -> 78960 bytes
-rw-r--r--fonts/Poppins-BlackItalic.woff2bin0 -> 55288 bytes
-rw-r--r--fonts/Poppins-Bold.eotbin0 -> 160460 bytes
-rw-r--r--fonts/Poppins-Bold.ttfbin0 -> 160304 bytes
-rw-r--r--fonts/Poppins-Bold.woffbin0 -> 72448 bytes
-rw-r--r--fonts/Poppins-Bold.woff2bin0 -> 51800 bytes
-rw-r--r--fonts/Poppins-BoldItalic.eotbin0 -> 183480 bytes
-rw-r--r--fonts/Poppins-BoldItalic.ttfbin0 -> 183296 bytes
-rw-r--r--fonts/Poppins-BoldItalic.woffbin0 -> 82700 bytes
-rw-r--r--fonts/Poppins-BoldItalic.woff2bin0 -> 58652 bytes
-rw-r--r--fonts/Poppins-ExtraBold.eotbin0 -> 159456 bytes
-rw-r--r--fonts/Poppins-ExtraBold.ttfbin0 -> 159264 bytes
-rw-r--r--fonts/Poppins-ExtraBold.woffbin0 -> 72296 bytes
-rw-r--r--fonts/Poppins-ExtraBold.woff2bin0 -> 51912 bytes
-rw-r--r--fonts/Poppins-ExtraBoldItalic.eotbin0 -> 180888 bytes
-rw-r--r--fonts/Poppins-ExtraBoldItalic.ttfbin0 -> 180684 bytes
-rw-r--r--fonts/Poppins-ExtraBoldItalic.woffbin0 -> 82324 bytes
-rw-r--r--fonts/Poppins-ExtraBoldItalic.woff2bin0 -> 58472 bytes
-rw-r--r--fonts/Poppins-ExtraLight.eotbin0 -> 168148 bytes
-rw-r--r--fonts/Poppins-ExtraLight.ttfbin0 -> 167952 bytes
-rw-r--r--fonts/Poppins-ExtraLight.woffbin0 -> 73396 bytes
-rw-r--r--fonts/Poppins-ExtraLight.woff2bin0 -> 52096 bytes
-rw-r--r--fonts/Poppins-ExtraLightItalic.eotbin0 -> 193204 bytes
-rw-r--r--fonts/Poppins-ExtraLightItalic.ttfbin0 -> 192996 bytes
-rw-r--r--fonts/Poppins-ExtraLightItalic.woffbin0 -> 83980 bytes
-rw-r--r--fonts/Poppins-ExtraLightItalic.woff2bin0 -> 59108 bytes
-rw-r--r--fonts/Poppins-Italic.eotbin0 -> 188844 bytes
-rw-r--r--fonts/Poppins-Italic.ttfbin0 -> 188680 bytes
-rw-r--r--fonts/Poppins-Italic.woffbin0 -> 84152 bytes
-rw-r--r--fonts/Poppins-Italic.woff2bin0 -> 59556 bytes
-rw-r--r--fonts/Poppins-Light.eotbin0 -> 166528 bytes
-rw-r--r--fonts/Poppins-Light.ttfbin0 -> 166352 bytes
-rw-r--r--fonts/Poppins-Light.woffbin0 -> 73396 bytes
-rw-r--r--fonts/Poppins-Light.woff2bin0 -> 52316 bytes
-rw-r--r--fonts/Poppins-LightItalic.eotbin0 -> 191388 bytes
-rw-r--r--fonts/Poppins-LightItalic.ttfbin0 -> 191200 bytes
-rw-r--r--fonts/Poppins-LightItalic.woffbin0 -> 84260 bytes
-rw-r--r--fonts/Poppins-LightItalic.woff2bin0 -> 59532 bytes
-rw-r--r--fonts/Poppins-Medium.eotbin0 -> 163164 bytes
-rw-r--r--fonts/Poppins-Medium.ttfbin0 -> 162984 bytes
-rw-r--r--fonts/Poppins-Medium.woffbin0 -> 72668 bytes
-rw-r--r--fonts/Poppins-Medium.woff2bin0 -> 51692 bytes
-rw-r--r--fonts/Poppins-MediumItalic.eotbin0 -> 187412 bytes
-rw-r--r--fonts/Poppins-MediumItalic.ttfbin0 -> 187220 bytes
-rw-r--r--fonts/Poppins-MediumItalic.woffbin0 -> 82740 bytes
-rw-r--r--fonts/Poppins-MediumItalic.woff2bin0 -> 58440 bytes
-rw-r--r--fonts/Poppins-Regular.eotbin0 -> 164800 bytes
-rw-r--r--fonts/Poppins-Regular.ttfbin0 -> 164632 bytes
-rw-r--r--fonts/Poppins-Regular.woffbin0 -> 73512 bytes
-rw-r--r--fonts/Poppins-Regular.woff2bin0 -> 52456 bytes
-rw-r--r--fonts/Poppins-SemiBold.eotbin0 -> 161912 bytes
-rw-r--r--fonts/Poppins-SemiBold.ttfbin0 -> 161724 bytes
-rw-r--r--fonts/Poppins-SemiBold.woffbin0 -> 73200 bytes
-rw-r--r--fonts/Poppins-SemiBold.woff2bin0 -> 52404 bytes
-rw-r--r--fonts/Poppins-SemiBoldItalic.eotbin0 -> 185588 bytes
-rw-r--r--fonts/Poppins-SemiBoldItalic.ttfbin0 -> 185388 bytes
-rw-r--r--fonts/Poppins-SemiBoldItalic.woffbin0 -> 83344 bytes
-rw-r--r--fonts/Poppins-SemiBoldItalic.woff2bin0 -> 59408 bytes
-rw-r--r--fonts/Poppins-Thin.eotbin0 -> 168432 bytes
-rw-r--r--fonts/Poppins-Thin.ttfbin0 -> 168260 bytes
-rw-r--r--fonts/Poppins-Thin.woffbin0 -> 69180 bytes
-rw-r--r--fonts/Poppins-Thin.woff2bin0 -> 48444 bytes
-rw-r--r--fonts/Poppins-ThinItalic.eotbin0 -> 194180 bytes
-rw-r--r--fonts/Poppins-ThinItalic.ttfbin0 -> 193996 bytes
-rw-r--r--fonts/Poppins-ThinItalic.woffbin0 -> 79908 bytes
-rw-r--r--fonts/Poppins-ThinItalic.woff2bin0 -> 55308 bytes
-rw-r--r--icons/explicit.svg1
-rw-r--r--icons/home-off.svg1
-rw-r--r--icons/home-on.svg1
-rw-r--r--icons/library-off.svg1
-rw-r--r--icons/library-on.svg1
-rw-r--r--icons/lyrics-not-playing.svg1
-rw-r--r--icons/lyrics-off.svg1
-rw-r--r--icons/lyrics-on.svg1
-rw-r--r--icons/next.svg1
-rw-r--r--icons/no-lyrics.svg1
-rw-r--r--icons/pause.svg1
-rw-r--r--icons/play.svg1
-rw-r--r--icons/previous.svg1
-rw-r--r--icons/repeat-off.svg1
-rw-r--r--icons/repeat-on.svg1
-rw-r--r--icons/settings-off.svg1
-rw-r--r--icons/settings-on.svg1
-rw-r--r--icons/shuffle-off.svg1
-rw-r--r--icons/shuffle-on.svg1
-rw-r--r--index.php218
-rw-r--r--js/frame.js25
-rw-r--r--js/logging.js3
-rw-r--r--js/navigation.js41
-rw-r--r--js/player.js255
-rw-r--r--js/seekbar.js29
-rw-r--r--logo/.DS_Storebin0 -> 6148 bytes
-rw-r--r--logo/128.pngbin0 -> 20500 bytes
-rw-r--r--logo/24.pngbin0 -> 7056 bytes
-rw-r--r--logo/256.pngbin0 -> 48792 bytes
-rw-r--r--logo/32.pngbin0 -> 7436 bytes
-rw-r--r--logo/48.pngbin0 -> 8974 bytes
-rw-r--r--logo/512.pngbin0 -> 155716 bytes
-rw-r--r--logo/56.pngbin0 -> 9657 bytes
-rw-r--r--logo/64.pngbin0 -> 9481 bytes
-rw-r--r--native.svg48
-rw-r--r--transparent.pngbin0 -> 1591 bytes
-rw-r--r--version1
150 files changed, 2535 insertions, 0 deletions
diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..fc5d1d7
--- /dev/null
+++ b/.DS_Store
Binary files differ
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5f6f9de
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+data/images
+data/metadata
+data/local
+data/sets \ No newline at end of file
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/Argon.iml b/.idea/Argon.iml
new file mode 100644
index 0000000..c956989
--- /dev/null
+++ b/.idea/Argon.iml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="WEB_MODULE" version="4">
+ <component name="NewModuleRootManager">
+ <content url="file://$MODULE_DIR$" />
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ </component>
+</module> \ No newline at end of file
diff --git a/.idea/deployment.xml b/.idea/deployment.xml
new file mode 100644
index 0000000..9ca48de
--- /dev/null
+++ b/.idea/deployment.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="PublishConfigData" autoUpload="Always" serverName="Minteck.org" remoteFilesAllowedToDisappearOnAutoupload="false">
+ <serverData>
+ <paths name="Minteck.org">
+ <serverdata>
+ <mappings>
+ <mapping deploy="/mnt/argon" local="$PROJECT_DIR$" web="/" />
+ </mappings>
+ </serverdata>
+ </paths>
+ </serverData>
+ <option name="myAutoUpload" value="ALWAYS" />
+ </component>
+</project> \ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..3d21248
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,6 @@
+<component name="InspectionProjectProfileManager">
+ <profile version="1.0">
+ <option name="myName" value="Project Default" />
+ <inspection_tool class="JSUndeclaredVariable" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
+ </profile>
+</component> \ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..717d13e
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectModuleManager">
+ <modules>
+ <module fileurl="file://$PROJECT_DIR$/.idea/Argon.iml" filepath="$PROJECT_DIR$/.idea/Argon.iml" />
+ </modules>
+ </component>
+</project> \ No newline at end of file
diff --git a/.idea/php.xml b/.idea/php.xml
new file mode 100644
index 0000000..7e5d55a
--- /dev/null
+++ b/.idea/php.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="PhpProjectSharedConfiguration" php_language_level="8.1" />
+</project> \ No newline at end of file
diff --git a/.idea/sshConfigs.xml b/.idea/sshConfigs.xml
new file mode 100644
index 0000000..3b08940
--- /dev/null
+++ b/.idea/sshConfigs.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="SshConfigs">
+ <configs>
+ <sshConfig host="ssh.minteck.org" id="17a6f0aa-4f80-4c21-8862-9cd09c8d61bf" keyPath="$USER_HOME$/.ssh/id_rsa" port="22465" nameFormat="DESCRIPTIVE" username="root" useOpenSSHConfig="true" />
+ </configs>
+ </component>
+</project> \ No newline at end of file
diff --git a/.idea/webServers.xml b/.idea/webServers.xml
new file mode 100644
index 0000000..89635a5
--- /dev/null
+++ b/.idea/webServers.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="WebServers">
+ <option name="servers">
+ <webServer id="2720c00d-2133-4e6f-9146-2563f8b73f95" name="Minteck.org">
+ <fileTransfer accessType="SFTP" host="ssh.minteck.org" port="22465" sshConfigId="17a6f0aa-4f80-4c21-8862-9cd09c8d61bf" sshConfig="root@ssh.minteck.org:22465 key" keyPair="true">
+ <advancedOptions>
+ <advancedOptions dataProtectionLevel="Private" keepAliveTimeout="0" passiveMode="true" shareSSLContext="true" />
+ </advancedOptions>
+ </fileTransfer>
+ </webServer>
+ </option>
+ </component>
+</project> \ No newline at end of file
diff --git a/_frame/about/index.php b/_frame/about/index.php
new file mode 100644
index 0000000..b1166ad
--- /dev/null
+++ b/_frame/about/index.php
@@ -0,0 +1,228 @@
+<?php if (str_ends_with($_SERVER['HTTP_HOST'], ".familine.minteck.org")) { $_FAMILINE = true; } else { $_FAMILINE = false; } function l($en, $fr) { global $_FAMILINE; if ($_FAMILINE) { return $fr; } else { return $en; } } $root = $_SERVER['DOCUMENT_ROOT']; $root = $_SERVER['DOCUMENT_ROOT']; if ($_FAMILINE) { require_once "/mnt/familine/app/session.php"; } ?>
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <title>Argon</title>
+ <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
+ <link rel="stylesheet" href="/css/fonts.css">
+ <link rel="stylesheet" href="/css/general.css">
+ <link rel="stylesheet" href="/css/loader.css">
+ <link rel="stylesheet" href="/css/header.css">
+ <link rel="stylesheet" href="/css/frame-about.css">
+ <link rel="stylesheet" href="/css/frame.css">
+ <link rel="stylesheet" href="/dark.css">
+ <meta name="HandheldFriendly" content="true" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
+</head>
+<body>
+<div id="argon-frame">
+ <div id="frame-header">
+ <?= l("About Argon", "À propos de Familine Musique") ?>
+ </div>
+ <div id="frame-contents">
+ <div id="frame-about-general">
+ <div id="frame-about-general-icon">
+ <img alt="<?= $_FAMILINE ? "Familine Musique" : "Argon" ?>" src="<?= $_FAMILINE ? "https://familine.minteck.org/icns/familine-music.svg" : "/logo/512.png" ?>" id="frame-about-general-icon">
+ </div>
+ <div id="frame-about-general-text">
+ <div id="frame-about-general-text-inner">
+ <b><?= $_FAMILINE ? "Familine Musique" : "Argon Media Platform" ?></b><br>
+ <?= $_FAMILINE ? "Argon v" : "Version " ?><?= file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/version"); ?>
+ </div>
+ </div>
+ </div>
+
+ <?php if (str_contains($_SERVER['HTTP_USER_AGENT'], "+AutomateCloud/") && !$_FAMILINE): ?>
+ <p>For more details and legal notices, go to the About Argon screen in the app's menus.</p>
+ <?php endif; ?>
+
+ <div id="frame-about-debug">
+ <b><?= l("Player Info", "Infos lecteur ") ?>:</b><br>
+
+ <div id="frame-about-debug--player" class="frame-about-section">
+ <span><?= l("Song ID", "ID morceau ") ?>:</span>
+ <span id="frame-about-debug--songId"><?= l("&lt;not playing&gt;", "&lt;pas de lecture&gt;") ?></span>
+
+ <span><?= l("Song Metadata", "Infos morc. ") ?>:</span>
+ <span id="frame-about-debug--songMetadata"><?= l("&lt;not playing&gt;", "&lt;pas de lecture&gt;") ?></span>
+
+ <span><?= l("Song Release Date", "Date sortie morc. ") ?>:</span>
+ <span id="frame-about-debug--songRelease"><?= l("&lt;not playing&gt;", "&lt;pas de lecture&gt;") ?></span>
+
+ <span><?= l("Previous Song", "Morc. précédent ") ?>:</span>
+ <span id="frame-about-debug--previousSong"><?= l("&lt;not playing&gt;", "&lt;pas de lecture&gt;") ?></span>
+
+ <span><?= l("Next Song", "Morc. suivant ") ?>:</span>
+ <span id="frame-about-debug--nextSong"><?= l("&lt;not playing&gt;", "&lt;pas de lecture&gt;") ?></span>
+
+ <span><?= l("Position", "Position ") ?>:</span>
+ <span id="frame-about-debug--position"><?= l("&lt;not playing&gt;", "&lt;pas de lecture&gt;") ?></span>
+
+ <span><?= l("Playback Quality", "Qualité lecture ") ?>:</span>
+ <span id="frame-about-debug--quality"><?= l("&lt;not playing&gt;", "&lt;pas de lecture&gt;") ?></span>
+
+ <span><?= l("Stream URL", "URL flux ") ?>:</span>
+ <span id="frame-about-debug--stream" class="frame-about-link" onclick="window.open(window.parent.ArgonPlayer._player.src);"><?= l("&lt;not playing&gt;", "&lt;pas de lecture&gt;") ?></span>
+
+ <span><?= l("Player State", "État lecteur ") ?>:</span>
+ <span id="frame-about-debug--state"><?= l("&lt;not playing&gt;", "&lt;pas de lecture&gt;") ?></span>
+
+ <span><?= l("Seeking", "Navigation ") ?>:</span>
+ <span id="frame-about-debug--seeking"><?= l("&lt;not playing&gt;", "&lt;pas de lecture&gt;") ?></span>
+
+ <span><?= l("Shuffle Mode", "Lect. aléatoire ") ?>:</span>
+ <span id="frame-about-debug--shuffle"><?= l("&lt;not playing&gt;", "&lt;pas de lecture&gt;") ?></span>
+
+ <span><?= l("Repeat Mode", "Lect. en boucle ") ?>:</span>
+ <span id="frame-about-debug--repeat"><?= l("&lt;not playing&gt;", "&lt;pas de lecture&gt;") ?></span>
+ </div>
+
+ <b><?= l("Server Info", "Infos serveur ") ?>:</b><br>
+
+ <div id="frame-about-debug--server" class="frame-about-section">
+ <span><?= l("PHP Version", "Version PHP ") ?>:</span>
+ <span id="frame-about-debug--php"><?= PHP_VERSION ?></span>
+
+ <span><?= l("Zend Version", "Version Zend ") ?>:</span>
+ <span id="frame-about-debug--php"><?= zend_version() ?></span>
+
+ <span><?= l("Web Server", "Serveur Web ") ?>:</span>
+ <span id="frame-about-debug--php"><?= $_SERVER['SERVER_SOFTWARE'] ?></span>
+
+ <span><?= l("Server Gateway", "Passerelle serveur ") ?>:</span>
+ <span id="frame-about-debug--gateway"><?= php_sapi_name() ?> (<?= $_SERVER['GATEWAY_INTERFACE'] ?>)</span>
+
+ <span><?= l("System Version", "Version système ") ?>:</span>
+ <span id="frame-about-debug--system"><?= php_uname("s") . " " . php_uname("r") ?></span>
+
+ <span><?= l("Server User", "Util. serveur ") ?>:</span>
+ <span id="frame-about-debug--system"><?= get_current_user() ?></span>
+ </div>
+
+ <b><?= l("Client Info", "Infos client ") ?>:</b><br>
+
+ <div id="frame-about-debug--client" class="frame-about-section">
+ <span><?= l("Logical Cores", "Cœurs logiques ") ?>:</span>
+ <span id="frame-about-debug--cores">...</span>
+
+ <span><?= l("Language", "Langue ") ?>:</span>
+ <span id="frame-about-debug--language">...</span>
+
+ <span><?= l("Touch Points", "Points de contact ") ?>:</span>
+ <span id="frame-about-debug--touch">...</span>
+
+ <span><?= l("Working Online", "En ligne ") ?>:</span>
+ <span id="frame-about-debug--online">...</span>
+
+ <span><?= l("Mobile Device", "Appareil mobile ") ?>:</span>
+ <span id="frame-about-debug--mobile">...</span>
+
+ <span><?= l("Navigator Brand", "Marque navigateur ") ?>:</span>
+ <span id="frame-about-debug--brands">...</span>
+ </div>
+ </div>
+
+ <script>
+ setInterval(() => {
+ document.getElementById("frame-about-debug--cores").innerText = navigator.hardwareConcurrency;
+ document.getElementById("frame-about-debug--language").innerText = navigator.language;
+ document.getElementById("frame-about-debug--touch").innerText = navigator.maxTouchPoints;
+ document.getElementById("frame-about-debug--online").innerText = navigator.onLine;
+ try {
+ document.getElementById("frame-about-debug--mobile").innerText = navigator.userAgentData.mobile;
+ } catch (e) {
+ document.getElementById("frame-about-debug--mobile").innerText = "null";
+ }
+ try {
+ document.getElementById("frame-about-debug--brands").innerText = navigator.userAgentData.brands.map(i => { return i.brand.trim() + "/" + i.version }).join(", ");
+ } catch (e) {
+ document.getElementById("frame-about-debug--brands").innerText = navigator.userAgent.replace(/(\([._;:\/\\A-Za-z 0-9,]*\))/gm, "").split(" ").filter(i => i.trim() !== "").filter(i => !i.startsWith("Mozilla")).join(", ");
+ }
+
+ if (window.parent.ArgonPlayer._current !== null) {
+ if (!window.parent.ArgonPlayer._shuffle) {
+ if (window.parent._argonSongsData.sorted[window.parent._argonSongsData.sorted.indexOf(window.parent.ArgonPlayer._current) + 1]) {
+ document.getElementById("frame-about-debug--nextSong").innerText = window.parent._argonSongsData.sorted[window.parent._argonSongsData.sorted.indexOf(window.parent.ArgonPlayer._current) + 1];
+ } else {
+ document.getElementById("frame-about-debug--nextSong").innerText = "<not applicable>";
+ }
+ } else {
+ document.getElementById("frame-about-debug--nextSong").innerText = "<shuffle on>";
+ }
+
+ if (!window.parent.ArgonPlayer._shuffle) {
+ if (window.parent._argonSongsData.sorted[window.parent._argonSongsData.sorted.indexOf(window.parent.ArgonPlayer._current) - 1]) {
+ document.getElementById("frame-about-debug--previousSong").innerText = window.parent._argonSongsData.sorted[window.parent._argonSongsData.sorted.indexOf(window.parent.ArgonPlayer._current) - 1];
+ } else {
+ document.getElementById("frame-about-debug--previousSong").innerText = "<?= l("<not applicable>", "<pas applicable>") ?>";
+ }
+ } else {
+ document.getElementById("frame-about-debug--previousSong").innerText = "<?= l("<shuffle on>", "<lect. aléa. activée>") ?>";
+ }
+
+ document.getElementById("frame-about-debug--songId").innerText = window.parent.ArgonPlayer._current;
+ document.getElementById("frame-about-debug--songMetadata").innerText = window.parent._argonSongsData.songs[window.parent.ArgonPlayer._current].name + " (" + window.parent._argonSongsData.songs[window.parent.ArgonPlayer._current].author + ", original<?= l("", " ") ?>: " + window.parent._argonSongsData.songs[window.parent.ArgonPlayer._current].original + ")";
+ document.getElementById("frame-about-debug--songRelease").innerText = window.parent._argonSongsData.songs[window.parent.ArgonPlayer._current].release;
+ document.getElementById("frame-about-debug--seeking").innerText = !window.parent.ArgonPlayer._seekbar;
+ document.getElementById("frame-about-debug--shuffle").innerText = window.parent.ArgonPlayer._shuffle;
+ document.getElementById("frame-about-debug--repeat").innerText = window.parent.ArgonPlayer._repeat;
+ switch (window.parent.ArgonPlayer._preferredQualityPreference[0] - 1 + 1) {
+ case 0:
+ document.getElementById("frame-about-debug--quality").innerText = window.parent.ArgonPlayer._currentQuality + " (<?= l("dynamic", "dynamique") ?>)";
+ break;
+ case 1:
+ document.getElementById("frame-about-debug--quality").innerText = window.parent.ArgonPlayer._currentQuality + " (<?= l("fixed", "fixe") ?>)";
+ break;
+ case 2:
+ document.getElementById("frame-about-debug--quality").innerText = window.parent.ArgonPlayer._currentQuality + " (original)";
+ break;
+ default:
+ document.getElementById("frame-about-debug--quality").innerText = window.parent.ArgonPlayer._currentQuality + " (<?= l("unknown", "inconnu") ?>)";
+ break;
+ }
+ document.getElementById("frame-about-debug--position").innerText = "(" + (window.parent.document.getElementById("player-seekbar").value / 1000).toFixed(3) + ") " + window.parent.ArgonPlayer._player.currentTime.toFixed(3) + "/" + window.parent.ArgonPlayer._player.duration.toFixed(3);
+ document.getElementById("frame-about-debug--stream").innerText = window.parent.ArgonPlayer._player.src;
+ switch (window.parent.ArgonPlayer._player.readyState) {
+ case 0:
+ document.getElementById("frame-about-debug--state").innerText = window.parent.ArgonPlayer._player.readyState + " (HAVE_NOTHING, <?= l("not playable", "ne peut pas lire") ?>)";
+ break;
+ case 1:
+ document.getElementById("frame-about-debug--state").innerText = window.parent.ArgonPlayer._player.readyState + " (HAVE_METADATA, <?= l("seekable", "navigable") ?>)";
+ break;
+ case 2:
+ document.getElementById("frame-about-debug--state").innerText = window.parent.ArgonPlayer._player.readyState + " (HAVE_CURRENT_DATA, <?= l("real-time download", "téléch. en temps réel") ?>)";
+ break;
+ case 3:
+ document.getElementById("frame-about-debug--state").innerText = window.parent.ArgonPlayer._player.readyState + " (HAVE_FUTURE_DATA, <?= l("ready", "prêt") ?>)";
+ break;
+ case 4:
+ document.getElementById("frame-about-debug--state").innerText = window.parent.ArgonPlayer._player.readyState + " (HAVE_ENOUGH_DATA, <?= l("uninterrupted", "ininterrompu") ?>)";
+ break;
+ default:
+ document.getElementById("frame-about-debug--state").innerText = window.parent.ArgonPlayer._player.readyState + " (<?= l("unknown", "inconnu") ?>)";
+ break;
+ }
+ } else {
+ document.getElementById("frame-about-debug--songId").innerText = "<?= l("<not playing>", "<pas de lecture>") ?>";
+ document.getElementById("frame-about-debug--songMetadata").innerText = "<?= l("<not playing>", "<pas de lecture>") ?>";
+ document.getElementById("frame-about-debug--songRelease").innerText = "<?= l("<not playing>", "<pas de lecture>") ?>";
+ document.getElementById("frame-about-debug--quality").innerText = "<?= l("<not playing>", "<pas de lecture>") ?>";
+ document.getElementById("frame-about-debug--position").innerText = "<?= l("<not playing>", "<pas de lecture>") ?>";
+ document.getElementById("frame-about-debug--stream").innerText = "<?= l("<not playing>", "<pas de lecture>") ?>";
+ document.getElementById("frame-about-debug--state").innerText = "<?= l("<not playing>", "<pas de lecture>") ?>";
+ document.getElementById("frame-about-debug--nextSong").innerText = "<?= l("<not playing>", "<pas de lecture>") ?>";
+ document.getElementById("frame-about-debug--previousSong").innerText = "<?= l("<not playing>", "<pas de lecture>") ?>";
+ }
+ })
+
+ width = Math.max(...Array.from(document.getElementsByClassName('frame-about-section')).map(i => { return Array.from(i.children).filter(i => i.id === "").map(i => { return i.clientWidth; }); }).map(i => { return Math.max(...i); }));
+
+ for (let item of [].concat(...Array.from(document.getElementsByClassName('frame-about-section')).map(i => Array.from(i.children).filter(i => i.id === "")))) {
+ item.style.width = width + "px";
+ }
+ </script>
+ </div>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/_frame/home/index.php b/_frame/home/index.php
new file mode 100644
index 0000000..c0f0c69
--- /dev/null
+++ b/_frame/home/index.php
@@ -0,0 +1,39 @@
+<?php if (str_ends_with($_SERVER['HTTP_HOST'], ".familine.minteck.org")) { $_FAMILINE = true; } else { $_FAMILINE = false; } function l($en, $fr) { global $_FAMILINE; if ($_FAMILINE) { return $fr; } else { return $en; } } $root = $_SERVER['DOCUMENT_ROOT']; $root = $_SERVER['DOCUMENT_ROOT']; if ($_FAMILINE) { require_once "/mnt/familine/app/session.php"; } ?>
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <title>Argon</title>
+ <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
+ <link rel="stylesheet" href="/css/fonts.css">
+ <link rel="stylesheet" href="/css/general.css">
+ <link rel="stylesheet" href="/css/header.css">
+ <link rel="stylesheet" href="/css/frame-home.css">
+ <link rel="stylesheet" href="/css/frame.css">
+ <link rel="stylesheet" href="/dark.css">
+ <meta name="HandheldFriendly" content="true" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
+</head>
+<body>
+<div id="argon-frame">
+ <div id="frame-header">
+ <?= l("Home", "Accueil") ?>
+ </div>
+ <div id="frame-contents">
+ <div id="frame-home-intro" <?= $_FAMILINE ? "style=\"filter: hue-rotate(250deg);\"" : "" ?>>
+ <img src="<?= str_contains($_SERVER['HTTP_USER_AGENT'], "+AutomateCloud/") ? ("/native.svg") : ($_FAMILINE ? "https://familine.minteck.org/icns/familine-music.svg" : "/logo/256.png") ?>" id="frame-home-logo" <?= $_FAMILINE ? "style=\"filter: hue-rotate(-250deg);\"" : "" ?>>
+ <div id="frame-home-welcome"><?= l("Welcome to the Argon Media Platform!", "Bienvenue sur Familine Musique !") ?></div>
+ <div id="frame-home-tagline"><?= l("High quality ad-free music from Minteck", "Musique de haute qualité et sans publicités de la famille") ?></div>
+ <button onclick="location.href='/_frame/library';" id="frame-home-button"><?= l("Browse Library", "Explorer la bibliothèque") ?></button>
+ <div id="frame-home-links">
+ <a onclick="location.href='/_frame/about';" id="frame-home-link-about" class="frame-home-link"><?= l("About Argon", "À propos") ?></a>
+ ·
+ <a onclick="location.href='/_frame/settings';" id="frame-home-link-settings" class="frame-home-link"><?= l("Preferences", "Préférences") ?></a>
+ ·
+ <a onclick="window.open('https://gitlab.minteck.org/explore/projects/topics/Argon');" id="frame-home-link-source" class="frame-home-link"><?= l("Source Code", "Code source") ?></a>
+ </div>
+ </div>
+ </div>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/_frame/index.php b/_frame/index.php
new file mode 100644
index 0000000..bd6bbfb
--- /dev/null
+++ b/_frame/index.php
@@ -0,0 +1,4 @@
+<?php
+
+header("Location: /_frame/home");
+die(); \ No newline at end of file
diff --git a/_frame/library.internal/index.php b/_frame/library.internal/index.php
new file mode 100644
index 0000000..04f766e
--- /dev/null
+++ b/_frame/library.internal/index.php
@@ -0,0 +1,7 @@
+<?php
+
+if (trim($_GET['_']) === "") {
+ require_once $_SERVER["DOCUMENT_ROOT"] . "/_frame/library.internal/main.php";
+} else {
+ require_once $_SERVER["DOCUMENT_ROOT"] . "/_frame/library.internal/view.php";
+} \ No newline at end of file
diff --git a/_frame/library.internal/main.php b/_frame/library.internal/main.php
new file mode 100644
index 0000000..7ce781e
--- /dev/null
+++ b/_frame/library.internal/main.php
@@ -0,0 +1,60 @@
+<?php if (str_ends_with($_SERVER['HTTP_HOST'], ".familine.minteck.org")) { $_FAMILINE = true; } else { $_FAMILINE = false; } function l($en, $fr) { global $_FAMILINE; if ($_FAMILINE) { return $fr; } else { return $en; } } $root = $_SERVER['DOCUMENT_ROOT']; $root = $_SERVER['DOCUMENT_ROOT']; if ($_FAMILINE) { require_once "/mnt/familine/app/session.php"; } ?>
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <title>Argon</title>
+ <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
+ <link rel="stylesheet" href="/css/fonts.css">
+ <link rel="stylesheet" href="/css/general.css">
+ <link rel="stylesheet" href="/css/header.css">
+ <link rel="stylesheet" href="/css/frame-library.css?_=a">
+ <link rel="stylesheet" href="/css/frame.css">
+ <link rel="stylesheet" href="/dark.css">
+ <meta name="HandheldFriendly" content="true" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
+</head>
+<body>
+<div id="argon-frame">
+ <div id="frame-header">
+ <?= l("Library", "Bibliothèque") ?>
+ </div>
+ <div id="frame-contents">
+ <?php $data = json_decode(file_get_contents("https://argon.minteck.org/api/get_list.php"), true); ?>
+ <div id="frame-library-listing">
+ <?php foreach ($data["listing"] as $item): ?>
+ <div onclick="if (!event.target.classList.contains('frame-library-item-part-song')) location.href='/_frame/library/<?= $item["_id"] ?>';" class="frame-library-item" id="frame-library-item--<?= $item["_type"] . "-" . $item["_id"] ?>">
+ <div class="frame-library-item-inner">
+ <div class="frame-library-item-cover">
+ <img alt="<?= l("Album art", "Couv. album") ?>" class="frame-library-item-cover-inner" src="/api/get_image.php?_=<?= $item["_id"] ?>">
+ </div>
+ <div class="frame-library-item-text">
+ <div class="frame-library-item-text-inner">
+ <div class="frame-library-item-text-title"><?= $item["name"] ?><?php if ($item["wip"]): ?> <span class="frame-library-wipBadge"><?= l("WIP", "En travail") ?></span><?php endif; ?></div>
+ <div class="frame-library-item-text-info"><?= $item["author"] ?> · <?= substr($item["release"], 0, 4); ?></div>
+ <?php if ($item["_type"] === "song"): ?>
+ <div class="frame-library-item-text-original"><?= $item["original"] === null ? l("Original Content", "Contenu original") : l("original by ", "original par ") . $item["original"] ?></div>
+ <?php else: ?>
+ <div class="frame-library-item-text-original"><?= count($item["songs"]) ?> <?= l("tracks", "morceaux") ?></div>
+ <?php endif; ?>
+ </div>
+ </div>
+ </div>
+ <?php if ($item["_type"] === "set"): ?>
+ <div class="frame-library-item-set">
+ <?php foreach ($item["songs"] as $index => $song): ?>
+ <div <?php if ($song["_released"]): ?>onclick="location.href='/_frame/library/<?= $song["_id"] ?>';"<?php endif; ?> class="frame-library-item-set-song frame-library-item-part-song <?php if (!$song["_released"]): ?>frame-library-item-set-song-wip<?php endif; ?>" id="frame-library-item-set-song--<?= $item["_id"] ?>--<?= $song["_id"] ?>">
+ <div class="frame-library-item-set-song-cover frame-library-item-part-song">
+ <img alt="<?= l("Album art", "Couv. album") ?>" class="frame-library-item-set-song-cover-inner frame-library-item-part-song" src="/api/get_image.php?_=<?= $song["_id"] ?>"></div>
+ <div class="frame-library-item-set-song-title frame-library-item-part-song"><?= $song["name"] ?><?php if ($song["wip"]): ?> <span class="frame-library-wipBadge"><?= l("WIP", "En travail") ?></span><?php endif; ?></div>
+ </div>
+ <?php endforeach; ?>
+ </div>
+ <?php endif; ?>
+ </div>
+ <?php endforeach; ?>
+ </div>
+ </div>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/_frame/library.internal/view.php b/_frame/library.internal/view.php
new file mode 100644
index 0000000..b66a4ca
--- /dev/null
+++ b/_frame/library.internal/view.php
@@ -0,0 +1,161 @@
+<?php if (str_ends_with($_SERVER['HTTP_HOST'], ".familine.minteck.org")) { $_FAMILINE = true; setlocale(LC_TIME, array('fr_FR.UTF-8','fr_FR@euro','fr_FR','french')); } else { $_FAMILINE = false; } function l($en, $fr) { global $_FAMILINE; if ($_FAMILINE) { return $fr; } else { return $en; } } $root = $_SERVER['DOCUMENT_ROOT']; $root = $_SERVER['DOCUMENT_ROOT'];
+
+$data = json_decode(file_get_contents("https://argon.minteck.org/api/get_list.php"), true);
+$views = json_decode(file_get_contents("/mnt/argon-cdn/3pad/data.json"), true);
+
+if (str_starts_with($_GET['_'], ":")) {
+ header("Location: /_frame/library");
+ die();
+}
+
+$set = null;
+$selected = null;
+foreach ($data["listing"] as $item) {
+ if ($item["_id"] === $_GET['_']) {
+ $selected = $item;
+ if ($item["_type"] === "set") {
+ $set = true;
+
+ foreach ($item["songs"] as $song) {
+ if ($song["_id"] === $_GET['_']) {
+ $selected = $song;
+ $set = false;
+ }
+ }
+ } else {
+ $set = false;
+ }
+ } else {
+ if ($item["_type"] === "set") {
+ foreach ($item["songs"] as $song) {
+ if ($song["_id"] === $_GET['_']) {
+ $selected = $song;
+ $set = false;
+ }
+ }
+ }
+ }
+}
+
+if ($selected === null) {
+ header("Location: /_frame/library");
+ die();
+}
+
+?>
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <title>Argon</title>
+ <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
+ <link rel="stylesheet" href="/css/fonts.css">
+ <link rel="stylesheet" href="/css/general.css">
+ <link rel="stylesheet" href="/css/header.css">
+ <link rel="stylesheet" href="/css/frame-library.css?_=a">
+ <link rel="stylesheet" href="/css/frame.css">
+ <link rel="stylesheet" href="/dark.css">
+ <meta name="HandheldFriendly" content="true" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
+</head>
+<body>
+<div id="argon-frame">
+ <div id="frame-header">
+ <?= l("Library", "Bibliothèque") ?>
+ </div>
+ <div id="frame-contents">
+ <div id="frame-viewer-header-outer" style="background-image: url('/api/get_image.php?_=<?= $selected["_id"] ?>');">
+ <div id="frame-viewer-header" <?= str_contains($_SERVER['HTTP_USER_AGENT'], "WebKit") || str_contains($_SERVER['HTTP_USER_AGENT'], "Chrome") ? 'style= "background: rgba(200, 200, 200, .5);"' : '' ?>>
+ <div id="frame-viewer-header-inner">
+ <div id="frame-viewer-header-cover">
+ <img id="frame-viewer-header-cover-inner" alt="<?= l("Album art", "Couv. album") ?>" src="/api/get_image.php?_=<?= $selected["_id"] ?>">
+ </div>
+ <div id="frame-viewer-header-text">
+ <div id="frame-viewer-header-text-inner">
+ <div id="frame-viewer-header-text-title"><?= $selected["name"] ?><?php if ($selected["wip"]): ?> <span class="frame-library-wipBadge"><?= l("WIP", "En travail") ?></span><?php endif; ?></div>
+ <div id="frame-viewer-header-text-info"><?= l("by", "par") ?> <?= $selected["author"] ?> · <?= l("released", "sorti le") ?> <?php
+ $fmt = new \IntlDateFormatter($_FAMILINE ? "fr_FR" : "en_US", NULL, NULL);
+ $fmt->setPattern('d MMMM yyyy');
+ echo $fmt->format(new DateTime($selected["release"]));
+ ?>
+ <?php
+
+ $playable = false;
+ $firstPlayableIndex = -1;
+ $notPlayableCount = 0;
+
+ if ($selected["_type"] === "set") {
+ foreach ($selected["songs"] as $index => $song) {
+ if ($song["_released"]) {
+ if ($firstPlayableIndex === -1) $firstPlayableIndex = $index;
+ $playable = true;
+ } else {
+ $notPlayableCount++;
+ }
+ }
+ } else if (!str_starts_with($selected["_id"], "_")) {
+ $playable = true;
+ }
+
+ ?>
+ <?php if ($playable): ?>
+ <?php if ((isset($selected["set"]) || $selected["_type"] === "song") && $selected["_released"]): ?>· <?= $views[$selected["_id"]]["_total"] ?> <?= l("listen", "écoute") ?><?= $views[$selected["_id"]] > 1 || $views[$selected["_id"]] === 0 ? "s" : "" ?><?php elseif ($selected["_type"] === "set"): ?>· <?php
+
+ $listens = 0;
+ foreach ($selected["songs"] as $song) {
+ $listens = $listens + $views[$song["_id"]]["_total"];
+ }
+ echo $listens;
+
+ ?> <?= l("listen", "écoute") ?><?= $listens > 1 || $listens === 0 ? "s" : "" ?>
+ <?php endif; ?>
+ <?php endif; ?></div>
+ <?php if ($selected["_type"] === "song" || isset($selected["set"])): ?>
+ <div class="frame-viewer-header-text-original"><?php if ($selected["set"] !== null): ?><?= l("in", "dans") ?> <a id="frame-viewer-header-text-linkToSet" onclick="location.href='/_frame/library/<?= $selected["set"]["_id"] ?>';"><?= $selected["set"]["name"] ?></a> · <?php endif; ?><?= $selected["original"] === null ? l("Original Content", "Contenu original") : l("original by", "original par") . " <a id='frame-viewer-header-text-linkToOriginal' onclick='window.open(&quot;" . $selected['link'] . "&quot)'>" . $selected["original"] . "</a>" ?></div>
+ <?php else: ?>
+ <div class="frame-viewer-header-text-original"><?= count($selected["songs"]) ?> tracks</div>
+ <?php endif; ?>
+ <?php if ($playable): ?>
+ <button onclick="window.parent.ArgonPlayer.play('<?= $selected["_type"] === "set" ? $selected["songs"][$firstPlayableIndex]["_id"] : $selected["_id"] ?>');" id="frame-viewer-header-play"><?= l("Play", "Lire") ?></button>
+ <?php if ($notPlayableCount > 0 && $playable): ?>
+ <span id="frame-viewer-header-notAvailableCount"><?= $notPlayableCount ?> <?= l("track", "morceau") ?><?= $notPlayableCount > 1 ? "s" : "" ?> <?= l("are not playable at the moment.", $notPlayableCount > 1 ? "ne sont pas accessibles en ce moment." : "n'est pas accessible en ce moment") ?></span>
+ <?php endif; ?>
+ <?php else: ?>
+ <div id="frame-viewer-header-notPlayable"><?= $selected["_type"] === "set" ? l("This playlist", "Cette liste de lecture") : l("This song", "Ce morceau") ?> <?= l("is not playable at the moment.", "n'est pas accessible en ce moment.") ?></div>
+ <?php endif; ?>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div id="frame-viewer-description">
+ <?php if (trim($selected["description"]) !== ""): ?>
+ <?= strip_tags($selected["description"]) ?>
+ <?php else: ?>
+ <span style="opacity:.5;"><?= l("No description provided.", "Aucune description donnée.") ?></span>
+ <?php endif; ?>
+ </div>
+ <?php if ((isset($selected["_type"]) && $selected["_type"] === "set") || isset($selected["set"])): ?>
+ <?php
+ if (isset($selected["_type"]) && $selected["_type"] === "set") $set = $selected;
+ if (isset($selected["set"])) {
+ $set = $selected["set"];
+ foreach ($set["songs"] as $index => $sid) {
+ if (isset($data["songs"][$sid])) $set["songs"][$index] = $data["songs"][$sid];
+ }
+ }
+ ?>
+ <div class="frame-library-item-set" id="frame-viewer-set">
+ <?php foreach ($set["songs"] as $index => $song): ?>
+ <div <?php if ($song["_released"]): ?>onclick="location.href='/_frame/library/<?= $song["_id"] ?>';"<?php endif; ?> class="frame-library-item-set-song frame-library-item-part-song <?php if (!$song["_released"]): ?>frame-library-item-set-song-wip<?php endif; ?>" id="frame-library-item-set-song--<?= $set["_id"] ?>--<?= $song["_id"] ?>">
+ <div class="frame-library-item-set-song-cover frame-library-item-part-song">
+ <img alt="<?= l("Album art", "Couv. album") ?>" class="frame-library-item-set-song-cover-inner frame-library-item-part-song" src="/api/get_image.php?_=<?= $song["_id"] ?>"></div>
+ <div class="frame-library-item-set-song-title frame-library-item-part-song"><?= isset($selected["set"]) && $song["_id"] === $selected["_id"] ? "<b>" . $song["name"] . "</b>" : $song["name"] ?><?php if ($song["wip"]): ?> <span class="frame-library-wipBadge"><?= l("WIP", "En travail") ?></span><?php endif; ?></div>
+ </div>
+ <?php endforeach; ?>
+ </div>
+ <?php endif; ?>
+ </div>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/_frame/lyrics/index.php b/_frame/lyrics/index.php
new file mode 100644
index 0000000..5b75d54
--- /dev/null
+++ b/_frame/lyrics/index.php
@@ -0,0 +1,99 @@
+<?php if (str_ends_with($_SERVER['HTTP_HOST'], ".familine.minteck.org")) { $_FAMILINE = true; } else { $_FAMILINE = false; } function l($en, $fr) { global $_FAMILINE; if ($_FAMILINE) { return $fr; } else { return $en; } } $root = $_SERVER['DOCUMENT_ROOT']; $root = $_SERVER['DOCUMENT_ROOT']; if ($_FAMILINE) { require_once "/mnt/familine/app/session.php"; } ?>
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <title>Argon</title>
+ <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
+ <link rel="stylesheet" href="/css/fonts.css">
+ <link rel="stylesheet" href="/css/general.css">
+ <link rel="stylesheet" href="/css/loader.css">
+ <link rel="stylesheet" href="/css/header.css">
+ <link rel="stylesheet" href="/css/frame-lyrics.css">
+ <link rel="stylesheet" href="/css/frame.css">
+ <link rel="stylesheet" href="/dark.css">
+ <meta name="HandheldFriendly" content="true" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
+</head>
+<body>
+<div id="argon-frame">
+ <div id="frame-header">
+ <?= l("Lyrics", "Paroles") ?>
+ </div>
+ <div id="frame-contents">
+ <div id="frame-lyrics-loader">
+ <div style="width:48px;height:48px;text-align: center;margin-left: auto;margin-right: auto;">
+ <svg class="circular-loader" viewBox="25 25 50 50">
+ <circle class="loader-path" cx="50" cy="50" r="20" fill="none"></circle>
+ </svg>
+ </div>
+ </div>
+ <div id="frame-lyrics-none" style="display:none;">
+ <div id="frame-lyrics-none-inner">
+ <img src="/icons/no-lyrics.svg" id="frame-lyrics-none-icon">
+ <div id="frame-lyrics-none-message"><?= l("No lyrics available for this song", "Pas de paroles disponibles pour ce morceau") ?></div>
+ </div>
+ </div>
+ <div id="frame-lyrics-play" style="display:none;">
+ <div id="frame-lyrics-play-inner">
+ <img src="/icons/lyrics-not-playing.svg" id="frame-lyrics-play-icon">
+ <div id="frame-lyrics-play-message"><?= l("No music is currently playing", "Aucun contenu n'est en cours de lecture") ?></div>
+ </div>
+ </div>
+ <div id="frame-lyrics-show" style="display:none;">
+ <div id="frame-lyrics-show-header">
+ <b id="frame-lyrics-show-header-author">Author</b> · <b id="frame-lyrics-show-header-title">Song Name</b><br>
+ <b id="frame-lyrics-show-header-original"><?= l("original creation", "création originalle") ?></b>
+ </div>
+ <br>
+ <div id="frame-lyrics-show-inner"></div>
+ <br>
+ <div id="frame-lyrics-show-copyright"></div>
+ </div>
+ </div>
+
+ <script>
+ _shouldRefresh = true;
+
+ document.onmousedown = () => {
+ _shouldRefresh = false;
+ }
+ document.onmouseup = () => {
+ _shouldRefresh = true;
+ }
+
+ setInterval(() => {
+ if (!_shouldRefresh) return;
+
+ document.getElementById("frame-lyrics-none").style.display = "none";
+ document.getElementById("frame-lyrics-show").style.display = "none";
+ document.getElementById("frame-lyrics-play").style.display = "none";
+ document.getElementById("frame-lyrics-loader").style.display = "none";
+
+ if (typeof window.parent.ArgonPlayer._current === "string") {
+ if (typeof window.parent._argonSongsData.songs[window.parent.ArgonPlayer._current].lyrics === "string") {
+ document.getElementById("frame-lyrics-show-header-title").innerHTML = window.parent._argonSongsData.songs[window.parent.ArgonPlayer._current].name;
+ document.getElementById("frame-lyrics-show-header-author").innerHTML = window.parent._argonSongsData.songs[window.parent.ArgonPlayer._current].author;
+ if (window.parent._argonSongsData.songs[window.parent.ArgonPlayer._current].original) {
+ document.getElementById("frame-lyrics-show-header-original").innerHTML = "<?= l("original by ", "original par ") ?>" + window.parent._argonSongsData.songs[window.parent.ArgonPlayer._current].original;
+ document.getElementById("frame-lyrics-show-copyright").innerText = "© " + window.parent._argonSongsData.songs[window.parent.ArgonPlayer._current].original;
+ } else {
+ document.getElementById("frame-lyrics-show-header-original").innerHTML = "<?= l("original creation", "creation originale") ?>";
+ document.getElementById("frame-lyrics-show-copyright").innerText = "© " + window.parent._argonSongsData.songs[window.parent.ArgonPlayer._current].author;
+ }
+ document.getElementById("frame-lyrics-show-inner").innerHTML = window.parent._argonSongsData.songs[window.parent.ArgonPlayer._current].lyrics.split("\n").join("<br>");
+ document.getElementById("frame-lyrics-show").style.display = "";
+ document.getElementById("frame-lyrics-loader").style.display = "none";
+ } else {
+ document.getElementById("frame-lyrics-none").style.display = "";
+ document.getElementById("frame-lyrics-loader").style.display = "none";
+ }
+ } else {
+ document.getElementById("frame-lyrics-play").style.display = "";
+ document.getElementById("frame-lyrics-loader").style.display = "none";
+ }
+ }, 1000)
+ </script>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/_frame/settings/index.php b/_frame/settings/index.php
new file mode 100644
index 0000000..b0ac0b7
--- /dev/null
+++ b/_frame/settings/index.php
@@ -0,0 +1,51 @@
+<?php if (str_ends_with($_SERVER['HTTP_HOST'], ".familine.minteck.org")) { $_FAMILINE = true; } else { $_FAMILINE = false; } function l($en, $fr) { global $_FAMILINE; if ($_FAMILINE) { return $fr; } else { return $en; } } $root = $_SERVER['DOCUMENT_ROOT']; $root = $_SERVER['DOCUMENT_ROOT']; if ($_FAMILINE) { require_once "/mnt/familine/app/session.php"; } ?>
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <title>Argon</title>
+ <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
+ <link rel="stylesheet" href="/css/fonts.css">
+ <link rel="stylesheet" href="/css/general.css">
+ <link rel="stylesheet" href="/css/loader.css">
+ <link rel="stylesheet" href="/css/header.css">
+ <link rel="stylesheet" href="/css/frame-settings.css">
+ <link rel="stylesheet" href="/css/frame.css">
+ <link rel="stylesheet" href="/dark.css">
+ <meta name="HandheldFriendly" content="true" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
+</head>
+<body>
+<div id="argon-frame">
+ <div id="frame-header">
+ <?= l("Preferences", "Préférences") ?>
+ </div>
+ <div id="frame-contents">
+ <?= l("Audio Quality", "Qualité audio") ?><br>
+ <select onchange="localStorage.setItem('quality', document.getElementById('frame-settings-quality').value); document.getElementById('frame-settings-quality-warning').style.display = document.getElementById('frame-settings-quality').value !== '0' ? '' : 'none'" id="frame-settings-quality">
+ <optgroup label="<?= l("Recommended Settings", "Paramètres recommendés") ?>">
+ <option value="0"><?= l("Automatically depending on network (recommended)", "Automatiquement selon le réseau (recommandé)") ?></option>
+ <option value="2"><?= l("Original audio quality", "Qualité audio originale") ?></option>
+ </optgroup>
+ <optgroup label="<?= l("Advanced", "Avancé") ?>">
+ <option value="1:ultrahighpcm"><?= l("Highest quality", "Qualité la plus haute") ?> (<?= l("CBR", "constant") ?> 460<?= l("kbps", " ko/s") ?>, 32<?= l("bit", " bits") ?>)</option>
+ <option value="1:veryhigh"><?= l("Higher quality", "Qualité plus haute") ?> (<?= l("CBR", "constant") ?> 320<?= l("kbps", " ko/s") ?>, 32<?= l("bit", " bits") ?>)</option>
+ <option value="1:high"><?= l("High quality", "Haute qualité") ?> (<?= l("VBR", "variable") ?> 245<?= l("kbps", " ko/s") ?>, 32<?= l("bit", " bits") ?>)</option>
+ <option value="1:medium"><?= l("Medium quality", "Qualité moyenne") ?> (<?= l("VBR", "variable") ?> 175<?= l("kbps", " ko/s") ?>, 16<?= l("bit", " bits") ?>)</option>
+ <option value="1:low"><?= l("Low quality", "Basse qualité") ?> (<?= l("VBR", "variable") ?> 130<?= l("kbps", " ko/s") ?>, 16<?= l("bit", " bits") ?>)</option>
+ <option value="1:verylow"><?= l("Slightly lower quality", "Qualité légèrement plus basse") ?> (<?= l("VBR", "variable") ?> 100<?= l("kbps", " ko/s") ?>, 16<?= l("bit", " bits") ?>)</option>
+ <option value="1:ultralow"><?= l("Lower quality", "Qualité plus basse") ?> (<?= l("VBR", "variable") ?> 85<?= l("kbps", " ko/s") ?>, 16<?= l("bit", " bits") ?>)</option>
+ <option value="1:superlow"><?= l("Lowest quality", "Qualité la plus basse") ?> (<?= l("VBR", "variable") ?> 65<?= l("kbps", " ko/s") ?>, 16<?= l("bit", " bits") ?>)</option>
+ </optgroup>
+ </select>
+ <div id="frame-settings-quality-warning" style="display:none;"><?= l("Using another audio quality setting than the default one may lead to audio not playing continuously due to low Internet connection or poor performance.", "Utiliser une autre option de qualité audio que celle par défaut peut empêcher l'audio d'être lu en continu en raison d'une mauvaise performance réseau ou système.") ?></div>
+ </div>
+
+ <script>
+ if (localStorage.getItem("quality") === null) localStorage.setItem('quality', '0');
+ document.getElementById('frame-settings-quality').value = localStorage.getItem("quality");
+ document.getElementById('frame-settings-quality-warning').style.display = document.getElementById('frame-settings-quality').value !== '0' ? '' : 'none';
+ </script>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/api/count_local_view.php b/api/count_local_view.php
new file mode 100644
index 0000000..6fd199e
--- /dev/null
+++ b/api/count_local_view.php
@@ -0,0 +1 @@
+<?php
diff --git a/api/get_app_css.php b/api/get_app_css.php
new file mode 100644
index 0000000..005c7ef
--- /dev/null
+++ b/api/get_app_css.php
@@ -0,0 +1,14 @@
+<?php
+
+header("Content-Type: application/json");
+
+$files = scandir($_SERVER['DOCUMENT_ROOT'] . "/css");
+$js = [];
+
+foreach ($files as $file) {
+ if (!str_starts_with($file, ".")) {
+ $js[] = "/css/" . $file;
+ }
+}
+
+die(json_encode($js)); \ No newline at end of file
diff --git a/api/get_app_js.php b/api/get_app_js.php
new file mode 100644
index 0000000..22da13f
--- /dev/null
+++ b/api/get_app_js.php
@@ -0,0 +1,14 @@
+<?php
+
+header("Content-Type: application/json");
+
+$files = scandir($_SERVER['DOCUMENT_ROOT'] . "/js");
+$js = [];
+
+foreach ($files as $file) {
+ if (!str_starts_with($file, ".")) {
+ $js[] = "/js/" . $file;
+ }
+}
+
+die(json_encode($js)); \ No newline at end of file
diff --git a/api/get_audio_files.php b/api/get_audio_files.php
new file mode 100644
index 0000000..a9a9146
--- /dev/null
+++ b/api/get_audio_files.php
@@ -0,0 +1,50 @@
+<?php
+
+if (isset($_GET["_"])) {
+ $f = $_GET["_"];
+} else {
+ die();
+}
+
+if (str_ends_with($_SERVER['HTTP_HOST'], ".familine.minteck.org")) {
+ $_FAMILINE = true;
+} else {
+ $_FAMILINE = false;
+}
+function l($en, $fr)
+{
+ global $_FAMILINE;
+ if ($_FAMILINE) {
+ return $fr;
+ } else {
+ return $en;
+ }
+}
+
+$root = $_SERVER['DOCUMENT_ROOT'];
+
+if (str_contains($f, "/") || trim($f) === "." || trim($f) === "..") die();
+
+header("Content-Type: application/json");
+
+$out = [
+ "original" => "https://" . ($_FAMILINE ? "music-audio-media01.familine.minteck.org" : "mediacdn.argon.minteck.org") . "/$f/original.flac",
+ "originalpcm" => "https://" . ($_FAMILINE ? "music-audio-media01.familine.minteck.org" : "mediacdn.argon.minteck.org") . "/$f/originalpcm.wav",
+ "ultrahigh" => "https://" . ($_FAMILINE ? "music-audio-media01.familine.minteck.org" : "mediacdn.argon.minteck.org") . "/$f/ultrahigh.flac",
+ "ultrahighpcm" => "https://" . ($_FAMILINE ? "music-audio-media01.familine.minteck.org" : "mediacdn.argon.minteck.org") . "/$f/ultrahighpcm.wav",
+ "veryhigh" => "https://" . ($_FAMILINE ? "music-audio-media01.familine.minteck.org" : "mediacdn.argon.minteck.org") . "/$f/veryhigh.mp3",
+ "high" => "https://" . ($_FAMILINE ? "music-audio-media01.familine.minteck.org" : "mediacdn.argon.minteck.org") . "/$f/high.mp3",
+ "medium" => "https://" . ($_FAMILINE ? "music-audio-media01.familine.minteck.org" : "mediacdn.argon.minteck.org") . "/$f/medium.mp3",
+ "low" => "https://" . ($_FAMILINE ? "music-audio-media01.familine.minteck.org" : "mediacdn.argon.minteck.org") . "/$f/low.mp3",
+ "verylow" => "https://" . ($_FAMILINE ? "music-audio-media01.familine.minteck.org" : "mediacdn.argon.minteck.org") . "/$f/verylow.mp3",
+ "ultralow" => "https://" . ($_FAMILINE ? "music-audio-media01.familine.minteck.org" : "mediacdn.argon.minteck.org") . "/$f/ultralow.mp3",
+ "superlow" => "https://" . ($_FAMILINE ? "music-audio-media01.familine.minteck.org" : "mediacdn.argon.minteck.org") . "/$f/superlow.mp3",
+];
+
+if (file_exists($_SERVER["DOCUMENT_ROOT"] . "/data/local/" . $f)) {
+ file_put_contents($_SERVER["DOCUMENT_ROOT"] . "/data/local/" . $f, ((int)file_get_contents($_SERVER["DOCUMENT_ROOT"] . "/data/local/" . $f)) + 1);
+} else {
+ file_put_contents($_SERVER["DOCUMENT_ROOT"] . "/data/local/" . $f, "1");
+}
+
+die(json_encode($out, JSON_PRETTY_PRINT)); \ No newline at end of file
diff --git a/api/get_image.php b/api/get_image.php
new file mode 100644
index 0000000..e8ea59f
--- /dev/null
+++ b/api/get_image.php
@@ -0,0 +1,20 @@
+<?php
+
+if (isset($_GET["_"])) {
+ $f = trim($_GET["_"]);
+} else {
+ die();
+}
+
+header("Content-Type: image/png");
+
+if (str_contains($f, "/") || str_contains($f, ".") || trim($f) === "") die();
+$f = str_replace(":", "-", $f);
+
+if (file_exists($_SERVER['DOCUMENT_ROOT'] . "/data/images/" . $f . ".png")) {
+ $url = $_SERVER['DOCUMENT_ROOT'] . "/data/images/" . $f . ".png";
+} else {
+ $url = "https://www.gravatar.com/avatar/" . md5($f) . "?f=y&d=identicon&s=256";
+}
+
+die(file_get_contents($url)); \ No newline at end of file
diff --git a/api/get_list.php b/api/get_list.php
new file mode 100644
index 0000000..dd92e8e
--- /dev/null
+++ b/api/get_list.php
@@ -0,0 +1,141 @@
+<?php
+
+header("Content-Type: application/json");
+
+$origList = [];
+
+foreach (scandir("/mnt/argon-cdn/files") as $s) {
+ if (!str_starts_with($s, ".")) {
+ $origList[] = $s;
+ }
+}
+
+foreach(scandir($_SERVER['DOCUMENT_ROOT'] . "/data/metadata") as $s) {
+ if (str_starts_with($s, "_")) {
+ $origList[] = substr($s, 0, -5);
+ }
+}
+
+$listSongs = [];
+$songs = [];
+foreach ($origList as $song) {
+ $listSongs[] = $song;
+ if (file_exists($_SERVER["DOCUMENT_ROOT"] . "/data/metadata/" . $song . ".json")) {
+ $songs[$song] = json_decode(file_get_contents($_SERVER["DOCUMENT_ROOT"] . "/data/metadata/" . $song . ".json"), true);
+ $songs[$song]["_id"] = $song;
+ $songs[$song]["_localViews"] = file_exists($_SERVER["DOCUMENT_ROOT"] . "/data/local/" . $song) ? (int)file_get_contents($_SERVER["DOCUMENT_ROOT"] . "/data/local/" . $song) : 0;
+ } else {
+ $songs[$song] = [
+ 'name' => $song,
+ 'original' => null,
+ 'link' => '',
+ 'author' => 'Minteck',
+ 'description' => '',
+ 'release' => '1970-01-01',
+ 'lyrics' => null,
+ 'wip' => false,
+ 'set' => null,
+ 'external' => [
+ 'youtube' => null,
+ 'soundcloud' => null
+ ]
+ ];
+ }
+}
+
+$sets = [];
+foreach (scandir($_SERVER["DOCUMENT_ROOT"] . "/data/sets") as $set) {
+ if (!str_starts_with($set, ".")) {
+ $set_data = json_decode(file_get_contents($_SERVER["DOCUMENT_ROOT"] . "/data/sets/" . $set), true);
+ $set_songs = [];
+
+ foreach ($set_data["songs"] as $song) {
+ if (in_array($song, $listSongs)) {
+ $set_songs[] = $song;
+ if (isset($songs[$song])) {
+ $songs[$song]["set"] = $set_data;
+ $songs[$song]["_id"] = $song;
+ $songs[$song]["_localViews"] = file_exists($_SERVER["DOCUMENT_ROOT"] . "/data/local/" . $song) ? (int)file_get_contents($_SERVER["DOCUMENT_ROOT"] . "/data/local/" . $song) : 0;
+ if (!isset($songs[$song]["_released"])) $songs[$song]["_released"] = true;
+ }
+ } else if (str_starts_with($song, ":")) {
+ $listSongs[] = $song;
+ $songs[$song] = [
+ 'name' => substr($song, 1),
+ 'original' => null,
+ 'link' => null,
+ 'author' => null,
+ 'description' => null,
+ 'release' => null,
+ 'lyrics' => null,
+ 'set' => null,
+ 'wip' => true,
+ '_released' => false
+ ];
+
+ $set_songs[] = $song;
+ $songs[$song]["set"] = $set_data;
+ $songs[$song]["_id"] = $song;
+ $songs[$song]["_localViews"] = file_exists($_SERVER["DOCUMENT_ROOT"] . "/data/local/" . $song) ? (int)file_get_contents($_SERVER["DOCUMENT_ROOT"] . "/data/local/" . $song) : 0;
+ if (!isset($songs[$song]["_released"])) $songs[$song]["_released"] = true;
+ }
+ }
+ $set_data["songs"] = $set_songs;
+ $sets[explode(".", $set)[0]] = $set_data;
+ }
+}
+
+$knownSongs = [];
+$list = [];
+foreach ($sets as $id => $set) {
+ $set["_type"] = "set";
+ $set["_id"] = $id;
+
+ foreach ($set["songs"] as $index => $song) {
+ $knownSongs[] = $song;
+ $songs[$song]["set"]["_id"] = $id;
+ $set["songs"][$index] = $songs[$song];
+ }
+
+ $list[] = $set;
+}
+foreach ($songs as $id => $song) {
+ $song["_type"] = "song";
+ $song["_id"] = $id;
+ if (!isset($song["_released"])) $song["_released"] = true;
+ if (!in_array($id, $knownSongs)) {
+ $knownSongs[] = $id;
+ $list[] = $song;
+ }
+}
+
+usort($list, function ($a, $b) {
+ return strtotime($a["release"]) - strtotime($b["release"]);
+});
+$list = array_reverse($list);
+
+$sorted = [];
+foreach ($list as $item) {
+ if ($item["_type"] === "song") {
+ if (!str_starts_with($item["_id"], ":") && !str_starts_with($item["_id"], "_")) {
+ $sorted[] = $item["_id"];
+ }
+ } else if ($item["_type"] === "set") {
+ $set_songs_sorted = array_reverse($item["songs"]);
+ foreach ($set_songs_sorted as $song) {
+ if (!str_starts_with($song["_id"], ":") && !str_starts_with($song["_id"], "_")) {
+ $sorted[] = $song["_id"];
+ }
+ }
+ }
+}
+$sorted = array_reverse($sorted);
+
+$out = [
+ "songs" => $songs,
+ "sets" => $sets,
+ "listing" => $list,
+ "sorted" => $sorted
+];
+
+die(json_encode($out, JSON_PRETTY_PRINT)); \ No newline at end of file
diff --git a/css/fonts.css b/css/fonts.css
new file mode 100644
index 0000000..2424ed4
--- /dev/null
+++ b/css/fonts.css
@@ -0,0 +1,216 @@
+@font-face {
+ font-family: 'Poppins';
+ src: url('/fonts/Poppins-MediumItalic.eot');
+ src: url('/fonts/Poppins-MediumItalic.eot?#iefix') format('embedded-opentype'),
+ url('/fonts/Poppins-MediumItalic.woff2') format('woff2'),
+ url('/fonts/Poppins-MediumItalic.woff') format('woff'),
+ url('/fonts/Poppins-MediumItalic.ttf') format('truetype');
+ font-weight: 500;
+ font-style: italic;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Poppins';
+ src: url('/fonts/Poppins-Light.eot');
+ src: url('/fonts/Poppins-Light.eot?#iefix') format('embedded-opentype'),
+ url('/fonts/Poppins-Light.woff2') format('woff2'),
+ url('/fonts/Poppins-Light.woff') format('woff'),
+ url('/fonts/Poppins-Light.ttf') format('truetype');
+ font-weight: 300;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Poppins';
+ src: url('/fonts/Poppins-LightItalic.eot');
+ src: url('/fonts/Poppins-LightItalic.eot?#iefix') format('embedded-opentype'),
+ url('/fonts/Poppins-LightItalic.woff2') format('woff2'),
+ url('/fonts/Poppins-LightItalic.woff') format('woff'),
+ url('/fonts/Poppins-LightItalic.ttf') format('truetype');
+ font-weight: 300;
+ font-style: italic;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Poppins';
+ src: url('/fonts/Poppins-Bold.eot');
+ src: url('/fonts/Poppins-Bold.eot?#iefix') format('embedded-opentype'),
+ url('/fonts/Poppins-Bold.woff2') format('woff2'),
+ url('/fonts/Poppins-Bold.woff') format('woff'),
+ url('/fonts/Poppins-Bold.ttf') format('truetype');
+ font-weight: bold;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Poppins';
+ src: url('/fonts/Poppins-Italic.eot');
+ src: url('/fonts/Poppins-Italic.eot?#iefix') format('embedded-opentype'),
+ url('/fonts/Poppins-Italic.woff2') format('woff2'),
+ url('/fonts/Poppins-Italic.woff') format('woff'),
+ url('/fonts/Poppins-Italic.ttf') format('truetype');
+ font-weight: normal;
+ font-style: italic;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Poppins';
+ src: url('/fonts/Poppins-ExtraBold.eot');
+ src: url('/fonts/Poppins-ExtraBold.eot?#iefix') format('embedded-opentype'),
+ url('/fonts/Poppins-ExtraBold.woff2') format('woff2'),
+ url('/fonts/Poppins-ExtraBold.woff') format('woff'),
+ url('/fonts/Poppins-ExtraBold.ttf') format('truetype');
+ font-weight: bold;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Poppins';
+ src: url('/fonts/Poppins-Regular.eot');
+ src: url('/fonts/Poppins-Regular.eot?#iefix') format('embedded-opentype'),
+ url('/fonts/Poppins-Regular.woff2') format('woff2'),
+ url('/fonts/Poppins-Regular.woff') format('woff'),
+ url('/fonts/Poppins-Regular.ttf') format('truetype');
+ font-weight: normal;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Poppins';
+ src: url('/fonts/Poppins-ThinItalic.eot');
+ src: url('/fonts/Poppins-ThinItalic.eot?#iefix') format('embedded-opentype'),
+ url('/fonts/Poppins-ThinItalic.woff2') format('woff2'),
+ url('/fonts/Poppins-ThinItalic.woff') format('woff'),
+ url('/fonts/Poppins-ThinItalic.ttf') format('truetype');
+ font-weight: 100;
+ font-style: italic;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Poppins';
+ src: url('/fonts/Poppins-Medium.eot');
+ src: url('/fonts/Poppins-Medium.eot?#iefix') format('embedded-opentype'),
+ url('/fonts/Poppins-Medium.woff2') format('woff2'),
+ url('/fonts/Poppins-Medium.woff') format('woff'),
+ url('/fonts/Poppins-Medium.ttf') format('truetype');
+ font-weight: 500;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Poppins';
+ src: url('/fonts/Poppins-ExtraLightItalic.eot');
+ src: url('/fonts/Poppins-ExtraLightItalic.eot?#iefix') format('embedded-opentype'),
+ url('/fonts/Poppins-ExtraLightItalic.woff2') format('woff2'),
+ url('/fonts/Poppins-ExtraLightItalic.woff') format('woff'),
+ url('/fonts/Poppins-ExtraLightItalic.ttf') format('truetype');
+ font-weight: 200;
+ font-style: italic;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Poppins';
+ src: url('/fonts/Poppins-SemiBold.eot');
+ src: url('/fonts/Poppins-SemiBold.eot?#iefix') format('embedded-opentype'),
+ url('/fonts/Poppins-SemiBold.woff2') format('woff2'),
+ url('/fonts/Poppins-SemiBold.woff') format('woff'),
+ url('/fonts/Poppins-SemiBold.ttf') format('truetype');
+ font-weight: 600;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Poppins';
+ src: url('/fonts/Poppins-Black.eot');
+ src: url('/fonts/Poppins-Black.eot?#iefix') format('embedded-opentype'),
+ url('/fonts/Poppins-Black.woff2') format('woff2'),
+ url('/fonts/Poppins-Black.woff') format('woff'),
+ url('/fonts/Poppins-Black.ttf') format('truetype');
+ font-weight: 900;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Poppins';
+ src: url('/fonts/Poppins-BlackItalic.eot');
+ src: url('/fonts/Poppins-BlackItalic.eot?#iefix') format('embedded-opentype'),
+ url('/fonts/Poppins-BlackItalic.woff2') format('woff2'),
+ url('/fonts/Poppins-BlackItalic.woff') format('woff'),
+ url('/fonts/Poppins-BlackItalic.ttf') format('truetype');
+ font-weight: 900;
+ font-style: italic;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Poppins';
+ src: url('/fonts/Poppins-ExtraBoldItalic.eot');
+ src: url('/fonts/Poppins-ExtraBoldItalic.eot?#iefix') format('embedded-opentype'),
+ url('/fonts/Poppins-ExtraBoldItalic.woff2') format('woff2'),
+ url('/fonts/Poppins-ExtraBoldItalic.woff') format('woff'),
+ url('/fonts/Poppins-ExtraBoldItalic.ttf') format('truetype');
+ font-weight: bold;
+ font-style: italic;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Poppins';
+ src: url('/fonts/Poppins-SemiBoldItalic.eot');
+ src: url('/fonts/Poppins-SemiBoldItalic.eot?#iefix') format('embedded-opentype'),
+ url('/fonts/Poppins-SemiBoldItalic.woff2') format('woff2'),
+ url('/fonts/Poppins-SemiBoldItalic.woff') format('woff'),
+ url('/fonts/Poppins-SemiBoldItalic.ttf') format('truetype');
+ font-weight: 600;
+ font-style: italic;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Poppins';
+ src: url('/fonts/Poppins-Thin.eot');
+ src: url('/fonts/Poppins-Thin.eot?#iefix') format('embedded-opentype'),
+ url('/fonts/Poppins-Thin.woff2') format('woff2'),
+ url('/fonts/Poppins-Thin.woff') format('woff'),
+ url('/fonts/Poppins-Thin.ttf') format('truetype');
+ font-weight: 100;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Poppins';
+ src: url('/fonts/Poppins-ExtraLight.eot');
+ src: url('/fonts/Poppins-ExtraLight.eot?#iefix') format('embedded-opentype'),
+ url('/fonts/Poppins-ExtraLight.woff2') format('woff2'),
+ url('/fonts/Poppins-ExtraLight.woff') format('woff'),
+ url('/fonts/Poppins-ExtraLight.ttf') format('truetype');
+ font-weight: 200;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Poppins';
+ src: url('/fonts/Poppins-BoldItalic.eot');
+ src: url('/fonts/Poppins-BoldItalic.eot?#iefix') format('embedded-opentype'),
+ url('/fonts/Poppins-BoldItalic.woff2') format('woff2'),
+ url('/fonts/Poppins-BoldItalic.woff') format('woff'),
+ url('/fonts/Poppins-BoldItalic.ttf') format('truetype');
+ font-weight: bold;
+ font-style: italic;
+ font-display: swap;
+}
+
diff --git a/css/frame-about.css b/css/frame-about.css
new file mode 100644
index 0000000..9a2e804
--- /dev/null
+++ b/css/frame-about.css
@@ -0,0 +1,52 @@
+#frame-about-general {
+ display: grid;
+ grid-template-columns: 64px 1fr;
+}
+
+#frame-about-general-icon {
+ width: 64px;
+}
+
+#frame-contents {
+ padding: 10px;
+}
+
+#frame-about-general-text {
+ display: flex;
+ align-items: center;
+ margin-left: 10px;
+}
+
+#frame-about-debug {
+ width: 100%;
+ font-size: 12px;
+ margin-top: 10px;
+}
+
+.frame-about-section * {
+ max-width: 50vw;
+ text-overflow: ellipsis;
+ overflow: hidden;
+}
+
+.frame-about-section {
+ display: grid;
+ grid-template-columns: max-content 1fr;
+ grid-column-gap: 5px;
+ margin-left: 15px;
+ margin-bottom: 10px;
+}
+
+.frame-about-link {
+ color: #0000c8;
+ text-decoration: underline;
+ cursor: pointer;
+}
+
+.frame-about-link:hover {
+ text-decoration: none;
+}
+
+.frame-about-link:active {
+ opacity: .5;
+} \ No newline at end of file
diff --git a/css/frame-home.css b/css/frame-home.css
new file mode 100644
index 0000000..82f171a
--- /dev/null
+++ b/css/frame-home.css
@@ -0,0 +1,51 @@
+#frame-home-intro {
+ margin-top: 40px;
+ text-align: center;
+ padding: 0 10px;
+}
+
+#frame-home-logo {
+ width: 128px;
+}
+
+#frame-home-welcome {
+ font-size: 30px;
+}
+
+#frame-home-tagline {
+ font-size: 18px;
+}
+
+#frame-home-button {
+ margin-top: 10px;
+ background: #002e47;
+ color: white;
+ border: 1px solid rgba(0, 0, 0, .25);
+ border-radius: 5px;
+ padding: 5px 10px;
+}
+
+#frame-home-button:hover {
+ background: #0e4665;
+}
+
+#frame-home-button:active, #frame-home-button:focus {
+ background: #1f648b;
+}
+
+#frame-home-links {
+ font-size: 12px;
+ margin-top: 10px;
+ opacity: .5;
+}
+
+.frame-home-link {
+ color: #0e4665;
+ cursor: pointer;
+ text-decoration: underline;
+ text-decoration-color: transparent;
+}
+
+.frame-home-link:hover {
+ text-decoration-color: inherit;
+} \ No newline at end of file
diff --git a/css/frame-library.css b/css/frame-library.css
new file mode 100644
index 0000000..9311796
--- /dev/null
+++ b/css/frame-library.css
@@ -0,0 +1,209 @@
+.frame-library-item {
+ border-bottom: 1px solid rgba(0, 0, 0, .1);
+ padding: 20px;
+ cursor: default;
+}
+
+.frame-library-item:hover {
+ background: rgba(0, 0, 0, .05);
+}
+
+.frame-library-item:active, .frame-library-item:focus {
+ background: rgba(0, 0, 0, .1);
+}
+
+.frame-library-item-inner {
+ display: grid;
+ grid-template-columns: 128px 1fr;
+}
+
+.frame-library-item-cover-inner {
+ width: 128px;
+}
+
+.frame-library-item-text {
+ display: flex;
+ align-items: center;
+}
+
+.frame-library-item-text-inner {
+ padding-left: 16px;
+ width: calc(100% - 16px);
+}
+
+.frame-library-item-text-title {
+ font-weight: 600;
+ font-size: 20px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ width: 50vw;
+}
+
+.frame-library-item-set {
+ margin-left: 144px;
+}
+
+@media (max-width: 500px) {
+ .frame-library-item-set {
+ margin-left: 0 !important;
+ }
+}
+
+.frame-library-item-set-song {
+ padding: 5px;
+ border-top: 1px solid rgba(0, 0, 0, .1);
+ border-bottom: 1px solid rgba(0, 0, 0, .1);
+ border-collapse: collapse;
+ display: grid;
+ grid-template-columns: 32px 1fr;
+}
+
+.frame-library-item-set-song:hover {
+ background: rgba(0, 0, 0, .05);
+}
+
+.frame-library-item-set-song:active {
+ background: rgba(0, 0, 0, .1);
+}
+
+.frame-library-item-set-song-cover-inner {
+ width: 32px;
+ height: 32px;
+ background: rgba(0, 0, 0, .25);
+ vertical-align: middle;
+}
+
+.frame-library-item-set-song-title {
+ display: flex;
+ align-items: center;
+ width: 100%;
+ overflow: hidden;
+ margin-left: 5px;
+ text-overflow: ellipsis;
+}
+
+#frame-viewer-header {
+ padding: 10px;
+ border-bottom: 1px solid rgba(0, 0, 0, .05);
+ background: rgba(200, 200, 200, 1);
+ backdrop-filter: blur(30px);
+ -webkit-backdrop-filter: blur(30px);
+}
+
+#frame-viewer-header-inner {
+ display: grid;
+ grid-template-columns: 128px 1fr;
+}
+
+#frame-viewer-header-cover-inner {
+ width: 128px;
+}
+
+#frame-viewer-header-text {
+ display: flex;
+ align-items: center;
+}
+
+#frame-viewer-header-text-inner {
+ margin-left: 15px;
+}
+
+#frame-viewer-header-text-title {
+ font-weight: 600;
+ font-size: 24px;
+}
+
+#frame-viewer-header-text-linkToSet, #frame-viewer-header-text-linkToOriginal {
+ cursor: pointer;
+ text-decoration: underline;
+ text-decoration-color: transparent;
+}
+
+#frame-viewer-header-text-linkToSet:hover, #frame-viewer-header-text-linkToOriginal:hover {
+ text-decoration-color: inherit;
+}
+
+#frame-viewer-header-text-linkToSet:active, #frame-viewer-header-text-linkToSet:focus, #frame-viewer-header-text-linkToOriginal:active, #frame-viewer-header-text-linkToOriginal:focus {
+ opacity: .75;
+}
+
+#frame-viewer-description {
+ padding: 10px;
+}
+
+#frame-viewer-header-play {
+ margin-top: 10px;
+ background: rgba(0, 0, 0, 0.25);
+ border: 1px solid rgba(0, 0, 0, .5);
+ border-radius: 5px;
+ padding: 5px 10px;
+ animation-fill-mode: both;
+ animation-duration: 2s;
+ animation-name: playbtn;
+ animation-iteration-count: infinite;
+ animation-timing-function: linear;
+ animation-direction: alternate-reverse;
+ color: white;
+}
+
+#frame-viewer-header-play:hover {
+ background: rgba(0, 0, 0, .5);
+ border-color: rgba(0, 0, 0, .75) !important;
+}
+
+#frame-viewer-header-play:active {
+ background: rgba(0, 0, 0, .75);
+ border-color: rgba(0, 0, 0, 1) !important;
+}
+
+@keyframes playbtn {
+ 0% { border-color: rgba(0, 0, 0, .5); }
+ 100% { border-color: rgba(175, 175, 175, .5); }
+}
+
+#frame-viewer-header-outer {
+ background-size: cover;
+ background-position: center;
+}
+
+#frame-viewer-set {
+ margin-left: 0;
+}
+
+.frame-library-item-set *:not(:nth-last-child(1)) {
+ border-bottom: none;
+}
+
+.frame-library-item-set-song-wip {
+ opacity: .3;
+ pointer-events: none;
+}
+
+.frame-library-wipBadge {
+ background: rgb(255, 190, 0);
+ border: 1px solid rgba(180, 146, 30, 0.5);
+ padding: 0px 5px;
+ border-radius: 999px;
+ margin-left: 5px;
+}
+
+#frame-viewer-header-notPlayable {
+ opacity: .5;
+ font-size: 12px;
+ margin-top: 10px;
+ margin-bottom: 10px;
+}
+
+#frame-viewer-header-notAvailableCount {
+ vertical-align: middle;
+ font-size: 12px;
+ color: #9f7700;
+ padding-left: 5px;
+}
+
+@media (max-width: 500px) {
+ #frame-viewer-header-notAvailableCount {
+ padding-left: 0;
+ display: block;
+ }
+} \ No newline at end of file
diff --git a/css/frame-lyrics.css b/css/frame-lyrics.css
new file mode 100644
index 0000000..0a5dec6
--- /dev/null
+++ b/css/frame-lyrics.css
@@ -0,0 +1,49 @@
+#frame-lyrics-loader, #frame-lyrics-none, #frame-lyrics-play {
+ display: flex;
+ position: fixed;
+ top: 45px;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ align-items: center;
+ justify-content: center;
+ text-align: center;
+}
+
+#frame-lyrics-none-icon {
+ width: 48px;
+}
+
+#frame-lyrics-none-message {
+ margin: 0 10px;
+ font-size: 20px;
+}
+
+#frame-lyrics-none {
+ opacity: .5;
+}
+
+#frame-lyrics-play-icon {
+ width: 48px;
+}
+
+#frame-lyrics-play-message {
+ margin: 0 10px;
+ font-size: 20px;
+}
+
+#frame-lyrics-play {
+ opacity: .5;
+}
+
+#frame-lyrics-show {
+ padding: 10px;
+}
+
+#frame-lyrics-show * {
+ cursor: text;
+}
+
+#frame-lyrics-show-copyright {
+ opacity: .5;
+} \ No newline at end of file
diff --git a/css/frame-settings.css b/css/frame-settings.css
new file mode 100644
index 0000000..d004710
--- /dev/null
+++ b/css/frame-settings.css
@@ -0,0 +1,15 @@
+#frame-contents {
+ padding: 10px;
+}
+
+#frame-settings-quality-warning {
+ color: #9f7700;
+ font-size: 12px;
+ padding-top: 5px;
+}
+
+#frame-settings-quality-notImplemented {
+ color: #9f0000;
+ font-size: 12px;
+ padding-top: 5px;
+} \ No newline at end of file
diff --git a/css/frame.css b/css/frame.css
new file mode 100644
index 0000000..aa0904b
--- /dev/null
+++ b/css/frame.css
@@ -0,0 +1,27 @@
+#frame {
+ position: fixed;
+ left: 65px;
+ bottom: 57px;
+ right: 0;
+ top: 0;
+}
+
+#frame-inner {
+ border: 0;
+ width: 100%;
+ height: 100%;
+}
+
+#frame-contents {
+ margin-top: 45px;
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ overflow: auto;
+}
+
+#frame-header {
+ overflow: hidden;
+} \ No newline at end of file
diff --git a/css/general.css b/css/general.css
new file mode 100644
index 0000000..7c330c2
--- /dev/null
+++ b/css/general.css
@@ -0,0 +1,11 @@
+html, body {
+ margin: 0;
+ padding: 0;
+ background: white;
+ color: black;
+}
+
+* {
+ font-family: "Poppins", -apple-system, "Segoe UI", "Ubuntu", sans-serif;
+ cursor: default;
+} \ No newline at end of file
diff --git a/css/header.css b/css/header.css
new file mode 100644
index 0000000..7227fa1
--- /dev/null
+++ b/css/header.css
@@ -0,0 +1,20 @@
+#frame-header {
+ position: fixed;
+ top: 0;
+ right: 0;
+ left: 0;
+ border-bottom: 1px solid rgba(0, 0, 0, .175);
+ background-color: rgba(0, 0, 0, .02);
+ transition: background-color 200ms;
+ overflow: auto;
+ padding: 10px;
+ display: flex;
+ align-items: center;
+ height: 24px;
+ font-size: 20px;
+ font-weight: 600;
+}
+
+#frame-header:hover {
+ background-color: rgba(0, 0, 0, .03);
+} \ No newline at end of file
diff --git a/css/loader.css b/css/loader.css
new file mode 100644
index 0000000..c0f2bce
--- /dev/null
+++ b/css/loader.css
@@ -0,0 +1,36 @@
+.loader-path {
+ fill: none;
+ stroke: black;
+ stroke-width: 3px;
+ stroke-linecap: round;
+ stroke-dasharray: 10, 10;
+}
+
+@keyframes rotate {
+ 100% {
+ transform: rotate(360deg);
+ }
+}
+
+.circular-loader {
+ animation: rotate 2s linear infinite;
+}
+
+@keyframes animate-stroke {
+ 0% {
+ stroke-dasharray: 1, 200;
+ stroke-dashoffset: 0;
+ }
+ 50% {
+ stroke-dasharray: 89, 200;
+ stroke-dashoffset: -35;
+ }
+ 100% {
+ stroke-dasharray: 89, 200;
+ stroke-dashoffset: -124;
+ }
+}
+
+.loader-path {
+ animation: animate-stroke 1.5s ease-in-out infinite;
+} \ No newline at end of file
diff --git a/css/navigation.css b/css/navigation.css
new file mode 100644
index 0000000..2be100e
--- /dev/null
+++ b/css/navigation.css
@@ -0,0 +1,56 @@
+#navigation-outer {
+ position: fixed;
+ top: 0;
+ bottom: 56px;
+ left: 0;
+ border-right: 1px solid rgba(0, 0, 0, .175);
+ background-color: rgba(0, 0, 0, .02);
+ transition: background-color 200ms;
+ width: calc(64px - 32px);
+ overflow: auto;
+ padding: 16px;
+ display: flex;
+ align-items: center;
+}
+
+#navigation {
+ width: 100%;
+}
+
+#navigation-outer:hover {
+ background-color: rgba(0, 0, 0, .03);
+}
+
+.navigation-item {
+ display: block;
+ text-align: center;
+ margin: 0 -16px;
+ padding: 12px;
+}
+
+.navigation-item:hover .navigation-item-icon {
+ opacity: .5;
+}
+
+.navigation-item:active .navigation-item-icon {
+ opacity: .25;
+}
+
+#navigation-about {
+ text-align: center;
+ padding-bottom: 12px;
+ margin: 0 -16px;
+ display: block;
+}
+
+#navigation-about-icon {
+ width: 32px;
+}
+
+#navigation-about:hover #navigation-about-icon {
+ opacity: .75;
+}
+
+#navigation-about:active #navigation-about-icon {
+ opacity: .5;
+} \ No newline at end of file
diff --git a/css/player.css b/css/player.css
new file mode 100644
index 0000000..08da44f
--- /dev/null
+++ b/css/player.css
@@ -0,0 +1,94 @@
+#player {
+ position: fixed;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ height: 56px;
+ width: 100%;
+ border-top: 1px solid rgba(0, 0, 0, .175);
+ background-color: rgba(0, 0, 0, .02);
+ transition: background-color 200ms;
+}
+
+#player:hover {
+ background-color: rgba(0, 0, 0, .03);
+}
+
+#player-inner {
+ text-align: center;
+ height: 100%;
+}
+
+#player-buttons, #player-info, #player-seekbar-area {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ height: 100%;
+ text-align: center;
+ vertical-align: middle;
+}
+
+.player-button {
+ display: inline-block;
+ padding: 5px;
+ width: 24px;
+ height: 24px;
+}
+
+.player-button:hover .player-button-icon {
+ opacity: .75;
+}
+
+.player-button:active .player-button-icon {
+ opacity: .5;
+}
+
+#player-artwork {
+ width: 42px;
+ height: 42px;
+ margin-right: 8px;
+ background: rgb(208, 208, 208);
+}
+
+#player-info-text {
+ font-size: 14px;
+ text-align: left;
+ display: grid;
+ grid-template-columns: 1fr;
+ grid-template-rows: 1fr 1fr;
+}
+
+#player-info-text-title {
+ font-weight: 600;
+}
+
+#player-info-text-title, #player-info-text-set, #player-info-text {
+ text-overflow: ellipsis;
+ width: 256px;
+ overflow: hidden;
+}
+
+#player-button-load-icon {
+ display: inline-block;
+ width: 24px;
+ height: 24px;
+}
+
+#player-seekbar {
+ width: 35vw;
+ margin: 0 10px;
+}
+
+#player-seekbar-elapsed, #player-seekbar-total {
+ font-size: 12px;
+ display: inline-block;
+ width: 48px;
+}
+
+#player-seekbar-total {
+ margin-right: 5px;
+}
+
+.player-button-disabled .player-button-icon {
+ opacity: .25 !important;
+} \ No newline at end of file
diff --git a/css/seekbar.css b/css/seekbar.css
new file mode 100644
index 0000000..67a3ec6
--- /dev/null
+++ b/css/seekbar.css
@@ -0,0 +1,34 @@
+#player-seekbar {
+ -webkit-appearance: none;
+ height: 2px;
+ border-radius: 999px;
+ background: #d3d3d3;
+ outline: none;
+ opacity: 0.7;
+ -webkit-transition: .2s;
+ transition: opacity .2s;
+}
+
+#player-seekbar::-webkit-slider-thumb {
+ -webkit-appearance: none;
+ appearance: none;
+ width: 10px;
+ height: 10px;
+ border-radius: 50%;
+ background: #282828;
+}
+
+#player-seekbar::-moz-range-thumb {
+ width: 10px;
+ height: 10px;
+ border-radius: 50%;
+ background: #282828;
+}
+
+#player-seekbar::-webkit-slider-thumb:hover {
+ background: rgba(40, 40, 40, 0.75);
+}
+
+#player-seekbar::-moz-range-thumb:hover {
+ background: rgba(40, 40, 40, 0.75);
+} \ No newline at end of file
diff --git a/dark.css b/dark.css
new file mode 100644
index 0000000..5774854
--- /dev/null
+++ b/dark.css
@@ -0,0 +1,62 @@
+@media (prefers-color-scheme: dark) {
+ body, html {
+ background: rgb(18, 18, 18) !important;
+ color: white !important;
+ }
+
+ #frame-viewer-header {
+ background: rgba(28, 28, 28, 1) !important;
+ }
+
+ #frame-viewer-header-play {
+ color: black !important;
+ }
+
+ #frame-header, #navigation-outer, #player {
+ border-color: rgba(255, 255, 255, .25) !important;
+ }
+
+ .frame-library-item, .frame-library-item-inner, .frame-library-item-set-song-cover, .frame-library-item-set-song-title, #frame-viewer-set, .navigation-item-icon, .player-button-icon, #frame-viewer-header-play, #frame-lyrics-none-icon, #frame-lyrics-play-icon {
+ filter: invert(1) !important;
+ }
+
+ #player-seekbar {
+ background: #ffffff !important;
+ }
+
+ #player-seekbar::-webkit-slider-thumb {
+ background: #aaaaaa !important;
+ }
+
+ #player-seekbar::-moz-range-thumb {
+ background: #aaaaaa !important;
+ }
+
+ #player-seekbar::-webkit-slider-thumb:hover {
+ background: #aaaaaabf !important;
+ }
+
+ #player-seekbar::-moz-range-thumb:hover {
+ background: #aaaaaabf !important;
+ }
+
+ #frame-header, #navigation-outer, #player {
+ background: rgb(32, 32, 32) !important;
+ }
+
+ #frame-header:hover, #navigation-outer:hover, #player:hover {
+ background: rgb(48, 48, 48) !important;
+ }
+
+ .frame-about-link, .frame-home-link {
+ filter: contrast(0.3) brightness(2) !important;
+ }
+
+ #argon-loader {
+ background: rgb(48, 48, 48) !important;
+ }
+
+ .loader-path {
+ stroke: white !important;
+ }
+} \ No newline at end of file
diff --git a/data/.DS_Store b/data/.DS_Store
new file mode 100644
index 0000000..a8a2009
--- /dev/null
+++ b/data/.DS_Store
Binary files differ
diff --git a/favicon.ico b/favicon.ico
new file mode 100644
index 0000000..a037397
--- /dev/null
+++ b/favicon.ico
Binary files differ
diff --git a/fonts/.DS_Store b/fonts/.DS_Store
new file mode 100644
index 0000000..5008ddf
--- /dev/null
+++ b/fonts/.DS_Store
Binary files differ
diff --git a/fonts/Poppins-Black.eot b/fonts/Poppins-Black.eot
new file mode 100644
index 0000000..502f526
--- /dev/null
+++ b/fonts/Poppins-Black.eot
Binary files differ
diff --git a/fonts/Poppins-Black.ttf b/fonts/Poppins-Black.ttf
new file mode 100644
index 0000000..7555c67
--- /dev/null
+++ b/fonts/Poppins-Black.ttf
Binary files differ
diff --git a/fonts/Poppins-Black.woff b/fonts/Poppins-Black.woff
new file mode 100644
index 0000000..a2e920c
--- /dev/null
+++ b/fonts/Poppins-Black.woff
Binary files differ
diff --git a/fonts/Poppins-Black.woff2 b/fonts/Poppins-Black.woff2
new file mode 100644
index 0000000..9e58a3c
--- /dev/null
+++ b/fonts/Poppins-Black.woff2
Binary files differ
diff --git a/fonts/Poppins-BlackItalic.eot b/fonts/Poppins-BlackItalic.eot
new file mode 100644
index 0000000..5d9fc1f
--- /dev/null
+++ b/fonts/Poppins-BlackItalic.eot
Binary files differ
diff --git a/fonts/Poppins-BlackItalic.ttf b/fonts/Poppins-BlackItalic.ttf
new file mode 100644
index 0000000..64b7af7
--- /dev/null
+++ b/fonts/Poppins-BlackItalic.ttf
Binary files differ
diff --git a/fonts/Poppins-BlackItalic.woff b/fonts/Poppins-BlackItalic.woff
new file mode 100644
index 0000000..f2e5aca
--- /dev/null
+++ b/fonts/Poppins-BlackItalic.woff
Binary files differ
diff --git a/fonts/Poppins-BlackItalic.woff2 b/fonts/Poppins-BlackItalic.woff2
new file mode 100644
index 0000000..8e3f7fb
--- /dev/null
+++ b/fonts/Poppins-BlackItalic.woff2
Binary files differ
diff --git a/fonts/Poppins-Bold.eot b/fonts/Poppins-Bold.eot
new file mode 100644
index 0000000..da1d371
--- /dev/null
+++ b/fonts/Poppins-Bold.eot
Binary files differ
diff --git a/fonts/Poppins-Bold.ttf b/fonts/Poppins-Bold.ttf
new file mode 100644
index 0000000..f8b0594
--- /dev/null
+++ b/fonts/Poppins-Bold.ttf
Binary files differ
diff --git a/fonts/Poppins-Bold.woff b/fonts/Poppins-Bold.woff
new file mode 100644
index 0000000..183b1a0
--- /dev/null
+++ b/fonts/Poppins-Bold.woff
Binary files differ
diff --git a/fonts/Poppins-Bold.woff2 b/fonts/Poppins-Bold.woff2
new file mode 100644
index 0000000..fd7e21b
--- /dev/null
+++ b/fonts/Poppins-Bold.woff2
Binary files differ
diff --git a/fonts/Poppins-BoldItalic.eot b/fonts/Poppins-BoldItalic.eot
new file mode 100644
index 0000000..6d51d88
--- /dev/null
+++ b/fonts/Poppins-BoldItalic.eot
Binary files differ
diff --git a/fonts/Poppins-BoldItalic.ttf b/fonts/Poppins-BoldItalic.ttf
new file mode 100644
index 0000000..4ca46ba
--- /dev/null
+++ b/fonts/Poppins-BoldItalic.ttf
Binary files differ
diff --git a/fonts/Poppins-BoldItalic.woff b/fonts/Poppins-BoldItalic.woff
new file mode 100644
index 0000000..5db9010
--- /dev/null
+++ b/fonts/Poppins-BoldItalic.woff
Binary files differ
diff --git a/fonts/Poppins-BoldItalic.woff2 b/fonts/Poppins-BoldItalic.woff2
new file mode 100644
index 0000000..948c335
--- /dev/null
+++ b/fonts/Poppins-BoldItalic.woff2
Binary files differ
diff --git a/fonts/Poppins-ExtraBold.eot b/fonts/Poppins-ExtraBold.eot
new file mode 100644
index 0000000..c7b3bf7
--- /dev/null
+++ b/fonts/Poppins-ExtraBold.eot
Binary files differ
diff --git a/fonts/Poppins-ExtraBold.ttf b/fonts/Poppins-ExtraBold.ttf
new file mode 100644
index 0000000..bed9184
--- /dev/null
+++ b/fonts/Poppins-ExtraBold.ttf
Binary files differ
diff --git a/fonts/Poppins-ExtraBold.woff b/fonts/Poppins-ExtraBold.woff
new file mode 100644
index 0000000..3de3510
--- /dev/null
+++ b/fonts/Poppins-ExtraBold.woff
Binary files differ
diff --git a/fonts/Poppins-ExtraBold.woff2 b/fonts/Poppins-ExtraBold.woff2
new file mode 100644
index 0000000..853b9d0
--- /dev/null
+++ b/fonts/Poppins-ExtraBold.woff2
Binary files differ
diff --git a/fonts/Poppins-ExtraBoldItalic.eot b/fonts/Poppins-ExtraBoldItalic.eot
new file mode 100644
index 0000000..bac61f1
--- /dev/null
+++ b/fonts/Poppins-ExtraBoldItalic.eot
Binary files differ
diff --git a/fonts/Poppins-ExtraBoldItalic.ttf b/fonts/Poppins-ExtraBoldItalic.ttf
new file mode 100644
index 0000000..1d6b76c
--- /dev/null
+++ b/fonts/Poppins-ExtraBoldItalic.ttf
Binary files differ
diff --git a/fonts/Poppins-ExtraBoldItalic.woff b/fonts/Poppins-ExtraBoldItalic.woff
new file mode 100644
index 0000000..1b84d73
--- /dev/null
+++ b/fonts/Poppins-ExtraBoldItalic.woff
Binary files differ
diff --git a/fonts/Poppins-ExtraBoldItalic.woff2 b/fonts/Poppins-ExtraBoldItalic.woff2
new file mode 100644
index 0000000..46fb380
--- /dev/null
+++ b/fonts/Poppins-ExtraBoldItalic.woff2
Binary files differ
diff --git a/fonts/Poppins-ExtraLight.eot b/fonts/Poppins-ExtraLight.eot
new file mode 100644
index 0000000..166a98d
--- /dev/null
+++ b/fonts/Poppins-ExtraLight.eot
Binary files differ
diff --git a/fonts/Poppins-ExtraLight.ttf b/fonts/Poppins-ExtraLight.ttf
new file mode 100644
index 0000000..f67f442
--- /dev/null
+++ b/fonts/Poppins-ExtraLight.ttf
Binary files differ
diff --git a/fonts/Poppins-ExtraLight.woff b/fonts/Poppins-ExtraLight.woff
new file mode 100644
index 0000000..2a46dee
--- /dev/null
+++ b/fonts/Poppins-ExtraLight.woff
Binary files differ
diff --git a/fonts/Poppins-ExtraLight.woff2 b/fonts/Poppins-ExtraLight.woff2
new file mode 100644
index 0000000..ee0c15e
--- /dev/null
+++ b/fonts/Poppins-ExtraLight.woff2
Binary files differ
diff --git a/fonts/Poppins-ExtraLightItalic.eot b/fonts/Poppins-ExtraLightItalic.eot
new file mode 100644
index 0000000..83656db
--- /dev/null
+++ b/fonts/Poppins-ExtraLightItalic.eot
Binary files differ
diff --git a/fonts/Poppins-ExtraLightItalic.ttf b/fonts/Poppins-ExtraLightItalic.ttf
new file mode 100644
index 0000000..4dbe2cc
--- /dev/null
+++ b/fonts/Poppins-ExtraLightItalic.ttf
Binary files differ
diff --git a/fonts/Poppins-ExtraLightItalic.woff b/fonts/Poppins-ExtraLightItalic.woff
new file mode 100644
index 0000000..243d34c
--- /dev/null
+++ b/fonts/Poppins-ExtraLightItalic.woff
Binary files differ
diff --git a/fonts/Poppins-ExtraLightItalic.woff2 b/fonts/Poppins-ExtraLightItalic.woff2
new file mode 100644
index 0000000..81bcf8b
--- /dev/null
+++ b/fonts/Poppins-ExtraLightItalic.woff2
Binary files differ
diff --git a/fonts/Poppins-Italic.eot b/fonts/Poppins-Italic.eot
new file mode 100644
index 0000000..596bad8
--- /dev/null
+++ b/fonts/Poppins-Italic.eot
Binary files differ
diff --git a/fonts/Poppins-Italic.ttf b/fonts/Poppins-Italic.ttf
new file mode 100644
index 0000000..ca84b2f
--- /dev/null
+++ b/fonts/Poppins-Italic.ttf
Binary files differ
diff --git a/fonts/Poppins-Italic.woff b/fonts/Poppins-Italic.woff
new file mode 100644
index 0000000..a465c1f
--- /dev/null
+++ b/fonts/Poppins-Italic.woff
Binary files differ
diff --git a/fonts/Poppins-Italic.woff2 b/fonts/Poppins-Italic.woff2
new file mode 100644
index 0000000..082d863
--- /dev/null
+++ b/fonts/Poppins-Italic.woff2
Binary files differ
diff --git a/fonts/Poppins-Light.eot b/fonts/Poppins-Light.eot
new file mode 100644
index 0000000..d569dde
--- /dev/null
+++ b/fonts/Poppins-Light.eot
Binary files differ
diff --git a/fonts/Poppins-Light.ttf b/fonts/Poppins-Light.ttf
new file mode 100644
index 0000000..94fa7da
--- /dev/null
+++ b/fonts/Poppins-Light.ttf
Binary files differ
diff --git a/fonts/Poppins-Light.woff b/fonts/Poppins-Light.woff
new file mode 100644
index 0000000..d2d37dd
--- /dev/null
+++ b/fonts/Poppins-Light.woff
Binary files differ
diff --git a/fonts/Poppins-Light.woff2 b/fonts/Poppins-Light.woff2
new file mode 100644
index 0000000..a8fc845
--- /dev/null
+++ b/fonts/Poppins-Light.woff2
Binary files differ
diff --git a/fonts/Poppins-LightItalic.eot b/fonts/Poppins-LightItalic.eot
new file mode 100644
index 0000000..2a5eda3
--- /dev/null
+++ b/fonts/Poppins-LightItalic.eot
Binary files differ
diff --git a/fonts/Poppins-LightItalic.ttf b/fonts/Poppins-LightItalic.ttf
new file mode 100644
index 0000000..f1b0564
--- /dev/null
+++ b/fonts/Poppins-LightItalic.ttf
Binary files differ
diff --git a/fonts/Poppins-LightItalic.woff b/fonts/Poppins-LightItalic.woff
new file mode 100644
index 0000000..78c3aa6
--- /dev/null
+++ b/fonts/Poppins-LightItalic.woff
Binary files differ
diff --git a/fonts/Poppins-LightItalic.woff2 b/fonts/Poppins-LightItalic.woff2
new file mode 100644
index 0000000..4e7ede7
--- /dev/null
+++ b/fonts/Poppins-LightItalic.woff2
Binary files differ
diff --git a/fonts/Poppins-Medium.eot b/fonts/Poppins-Medium.eot
new file mode 100644
index 0000000..5930652
--- /dev/null
+++ b/fonts/Poppins-Medium.eot
Binary files differ
diff --git a/fonts/Poppins-Medium.ttf b/fonts/Poppins-Medium.ttf
new file mode 100644
index 0000000..a0592a0
--- /dev/null
+++ b/fonts/Poppins-Medium.ttf
Binary files differ
diff --git a/fonts/Poppins-Medium.woff b/fonts/Poppins-Medium.woff
new file mode 100644
index 0000000..ade6331
--- /dev/null
+++ b/fonts/Poppins-Medium.woff
Binary files differ
diff --git a/fonts/Poppins-Medium.woff2 b/fonts/Poppins-Medium.woff2
new file mode 100644
index 0000000..d7c16dc
--- /dev/null
+++ b/fonts/Poppins-Medium.woff2
Binary files differ
diff --git a/fonts/Poppins-MediumItalic.eot b/fonts/Poppins-MediumItalic.eot
new file mode 100644
index 0000000..ba03a87
--- /dev/null
+++ b/fonts/Poppins-MediumItalic.eot
Binary files differ
diff --git a/fonts/Poppins-MediumItalic.ttf b/fonts/Poppins-MediumItalic.ttf
new file mode 100644
index 0000000..ff6e576
--- /dev/null
+++ b/fonts/Poppins-MediumItalic.ttf
Binary files differ
diff --git a/fonts/Poppins-MediumItalic.woff b/fonts/Poppins-MediumItalic.woff
new file mode 100644
index 0000000..3ff3847
--- /dev/null
+++ b/fonts/Poppins-MediumItalic.woff
Binary files differ
diff --git a/fonts/Poppins-MediumItalic.woff2 b/fonts/Poppins-MediumItalic.woff2
new file mode 100644
index 0000000..502ea3e
--- /dev/null
+++ b/fonts/Poppins-MediumItalic.woff2
Binary files differ
diff --git a/fonts/Poppins-Regular.eot b/fonts/Poppins-Regular.eot
new file mode 100644
index 0000000..a909b0b
--- /dev/null
+++ b/fonts/Poppins-Regular.eot
Binary files differ
diff --git a/fonts/Poppins-Regular.ttf b/fonts/Poppins-Regular.ttf
new file mode 100644
index 0000000..3c0b76d
--- /dev/null
+++ b/fonts/Poppins-Regular.ttf
Binary files differ
diff --git a/fonts/Poppins-Regular.woff b/fonts/Poppins-Regular.woff
new file mode 100644
index 0000000..2b18f02
--- /dev/null
+++ b/fonts/Poppins-Regular.woff
Binary files differ
diff --git a/fonts/Poppins-Regular.woff2 b/fonts/Poppins-Regular.woff2
new file mode 100644
index 0000000..bd4e3bd
--- /dev/null
+++ b/fonts/Poppins-Regular.woff2
Binary files differ
diff --git a/fonts/Poppins-SemiBold.eot b/fonts/Poppins-SemiBold.eot
new file mode 100644
index 0000000..1161f0f
--- /dev/null
+++ b/fonts/Poppins-SemiBold.eot
Binary files differ
diff --git a/fonts/Poppins-SemiBold.ttf b/fonts/Poppins-SemiBold.ttf
new file mode 100644
index 0000000..515996d
--- /dev/null
+++ b/fonts/Poppins-SemiBold.ttf
Binary files differ
diff --git a/fonts/Poppins-SemiBold.woff b/fonts/Poppins-SemiBold.woff
new file mode 100644
index 0000000..06273fe
--- /dev/null
+++ b/fonts/Poppins-SemiBold.woff
Binary files differ
diff --git a/fonts/Poppins-SemiBold.woff2 b/fonts/Poppins-SemiBold.woff2
new file mode 100644
index 0000000..a5b4808
--- /dev/null
+++ b/fonts/Poppins-SemiBold.woff2
Binary files differ
diff --git a/fonts/Poppins-SemiBoldItalic.eot b/fonts/Poppins-SemiBoldItalic.eot
new file mode 100644
index 0000000..9e396f5
--- /dev/null
+++ b/fonts/Poppins-SemiBoldItalic.eot
Binary files differ
diff --git a/fonts/Poppins-SemiBoldItalic.ttf b/fonts/Poppins-SemiBoldItalic.ttf
new file mode 100644
index 0000000..31f7a33
--- /dev/null
+++ b/fonts/Poppins-SemiBoldItalic.ttf
Binary files differ
diff --git a/fonts/Poppins-SemiBoldItalic.woff b/fonts/Poppins-SemiBoldItalic.woff
new file mode 100644
index 0000000..8a1bbe3
--- /dev/null
+++ b/fonts/Poppins-SemiBoldItalic.woff
Binary files differ
diff --git a/fonts/Poppins-SemiBoldItalic.woff2 b/fonts/Poppins-SemiBoldItalic.woff2
new file mode 100644
index 0000000..9d4729a
--- /dev/null
+++ b/fonts/Poppins-SemiBoldItalic.woff2
Binary files differ
diff --git a/fonts/Poppins-Thin.eot b/fonts/Poppins-Thin.eot
new file mode 100644
index 0000000..72d432d
--- /dev/null
+++ b/fonts/Poppins-Thin.eot
Binary files differ
diff --git a/fonts/Poppins-Thin.ttf b/fonts/Poppins-Thin.ttf
new file mode 100644
index 0000000..e77b13d
--- /dev/null
+++ b/fonts/Poppins-Thin.ttf
Binary files differ
diff --git a/fonts/Poppins-Thin.woff b/fonts/Poppins-Thin.woff
new file mode 100644
index 0000000..bcb1341
--- /dev/null
+++ b/fonts/Poppins-Thin.woff
Binary files differ
diff --git a/fonts/Poppins-Thin.woff2 b/fonts/Poppins-Thin.woff2
new file mode 100644
index 0000000..9f34f03
--- /dev/null
+++ b/fonts/Poppins-Thin.woff2
Binary files differ
diff --git a/fonts/Poppins-ThinItalic.eot b/fonts/Poppins-ThinItalic.eot
new file mode 100644
index 0000000..c30e173
--- /dev/null
+++ b/fonts/Poppins-ThinItalic.eot
Binary files differ
diff --git a/fonts/Poppins-ThinItalic.ttf b/fonts/Poppins-ThinItalic.ttf
new file mode 100644
index 0000000..6c07a86
--- /dev/null
+++ b/fonts/Poppins-ThinItalic.ttf
Binary files differ
diff --git a/fonts/Poppins-ThinItalic.woff b/fonts/Poppins-ThinItalic.woff
new file mode 100644
index 0000000..6459aa0
--- /dev/null
+++ b/fonts/Poppins-ThinItalic.woff
Binary files differ
diff --git a/fonts/Poppins-ThinItalic.woff2 b/fonts/Poppins-ThinItalic.woff2
new file mode 100644
index 0000000..8578cb6
--- /dev/null
+++ b/fonts/Poppins-ThinItalic.woff2
Binary files differ
diff --git a/icons/explicit.svg b/icons/explicit.svg
new file mode 100644
index 0000000..b69b615
--- /dev/null
+++ b/icons/explicit.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V5h14v14zm-4-4h-4v-2h4v-2h-4V9h4V7H9v10h6z"/></svg> \ No newline at end of file
diff --git a/icons/home-off.svg b/icons/home-off.svg
new file mode 100644
index 0000000..403bf3b
--- /dev/null
+++ b/icons/home-off.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M12 5.69l5 4.5V18h-2v-6H9v6H7v-7.81l5-4.5M12 3L2 12h3v8h6v-6h2v6h6v-8h3L12 3z"/></svg> \ No newline at end of file
diff --git a/icons/home-on.svg b/icons/home-on.svg
new file mode 100644
index 0000000..8584f7e
--- /dev/null
+++ b/icons/home-on.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0z" fill="none"/><path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/></svg> \ No newline at end of file
diff --git a/icons/library-off.svg b/icons/library-off.svg
new file mode 100644
index 0000000..b6732c4
--- /dev/null
+++ b/icons/library-off.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M20 2H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 14H8V4h12v12zm-7.5-1c1.38 0 2.5-1.12 2.5-2.5V7h3V5h-4v5.51c-.42-.32-.93-.51-1.5-.51-1.38 0-2.5 1.12-2.5 2.5s1.12 2.5 2.5 2.5zM4 6H2v14c0 1.1.9 2 2 2h14v-2H4V6z"/></svg> \ No newline at end of file
diff --git a/icons/library-on.svg b/icons/library-on.svg
new file mode 100644
index 0000000..a0022b7
--- /dev/null
+++ b/icons/library-on.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0z" fill="none"/><path d="M20 2H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-2 5h-3v5.5c0 1.38-1.12 2.5-2.5 2.5S10 13.88 10 12.5s1.12-2.5 2.5-2.5c.57 0 1.08.19 1.5.51V5h4v2zM4 6H2v14c0 1.1.9 2 2 2h14v-2H4V6z"/></svg> \ No newline at end of file
diff --git a/icons/lyrics-not-playing.svg b/icons/lyrics-not-playing.svg
new file mode 100644
index 0000000..873b20e
--- /dev/null
+++ b/icons/lyrics-not-playing.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M12 3v10.55c-.59-.34-1.27-.55-2-.55-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4V7h4V3h-6zm-2 16c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"/></svg> \ No newline at end of file
diff --git a/icons/lyrics-off.svg b/icons/lyrics-off.svg
new file mode 100644
index 0000000..be0127f
--- /dev/null
+++ b/icons/lyrics-off.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><g><rect fill="none" height="24" width="24"/></g><g><g><rect height="2" width="7" x="6" y="6"/><rect height="2" width="4" x="6" y="12"/><path d="M15,11.97V16H6l-2,2V4h11v2.03c0.52-0.69,1.2-1.25,2-1.6V4c0-1.1-0.9-2-2-2H4C2.9,2,2.01,2.9,2.01,4L2,22l4-4h9 c1.1,0,2-0.9,2-2v-2.42C16.2,13.22,15.52,12.66,15,11.97z"/><rect height="2" width="7" x="6" y="9"/><path d="M20,6.18C19.69,6.07,19.35,6,19,6c-1.66,0-3,1.34-3,3c0,1.66,1.34,3,3,3s3-1.34,3-3V3h2V1h-4V6.18z"/></g></g></svg> \ No newline at end of file
diff --git a/icons/lyrics-on.svg b/icons/lyrics-on.svg
new file mode 100644
index 0000000..1f26657
--- /dev/null
+++ b/icons/lyrics-on.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><g><rect fill="none" height="24" width="24"/></g><g><g><path d="M14,9c0-2.04,1.24-3.79,3-4.57V4c0-1.1-0.9-2-2-2H4C2.9,2,2.01,2.9,2.01,4L2,22l4-4h9c1.1,0,2-0.9,2-2v-2.42 C15.24,12.8,14,11.05,14,9z M10,14H6v-2h4V14z M13,11H6V9h7V11z M13,8H6V6h7V8z"/><path d="M20,6.18C19.69,6.07,19.35,6,19,6c-1.66,0-3,1.34-3,3c0,1.66,1.34,3,3,3s3-1.34,3-3V3h2V1h-4V6.18z"/></g></g></svg> \ No newline at end of file
diff --git a/icons/next.svg b/icons/next.svg
new file mode 100644
index 0000000..48b0ea9
--- /dev/null
+++ b/icons/next.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0z" fill="none"/><path d="M6 18l8.5-6L6 6v12zM16 6v12h2V6h-2z"/></svg> \ No newline at end of file
diff --git a/icons/no-lyrics.svg b/icons/no-lyrics.svg
new file mode 100644
index 0000000..64e9163
--- /dev/null
+++ b/icons/no-lyrics.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 14c1.66 0 2.99-1.34 2.99-3L15 5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3zm-1.2-9.1c0-.66.54-1.2 1.2-1.2.66 0 1.2.54 1.2 1.2l-.01 6.2c0 .66-.53 1.2-1.19 1.2-.66 0-1.2-.54-1.2-1.2V4.9zm6.5 6.1c0 3-2.54 5.1-5.3 5.1S6.7 14 6.7 11H5c0 3.41 2.72 6.23 6 6.72V21h2v-3.28c3.28-.48 6-3.3 6-6.72h-1.7z"/></svg> \ No newline at end of file
diff --git a/icons/pause.svg b/icons/pause.svg
new file mode 100644
index 0000000..4104cb0
--- /dev/null
+++ b/icons/pause.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0z" fill="none"/><path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/></svg> \ No newline at end of file
diff --git a/icons/play.svg b/icons/play.svg
new file mode 100644
index 0000000..178bd3a
--- /dev/null
+++ b/icons/play.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0z" fill="none"/><path d="M8 5v14l11-7z"/></svg> \ No newline at end of file
diff --git a/icons/previous.svg b/icons/previous.svg
new file mode 100644
index 0000000..7347272
--- /dev/null
+++ b/icons/previous.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0z" fill="none"/><path d="M6 6h2v12H6zm3.5 6l8.5 6V6z"/></svg> \ No newline at end of file
diff --git a/icons/repeat-off.svg b/icons/repeat-off.svg
new file mode 100644
index 0000000..cd41e84
--- /dev/null
+++ b/icons/repeat-off.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0z" fill="none"/><path d="M7 7h10v3l4-4-4-4v3H5v6h2V7zm10 10H7v-3l-4 4 4 4v-3h12v-6h-2v4z"/></svg> \ No newline at end of file
diff --git a/icons/repeat-on.svg b/icons/repeat-on.svg
new file mode 100644
index 0000000..9047ec9
--- /dev/null
+++ b/icons/repeat-on.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M21 1H3c-1.1 0-2 .9-2 2v18c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V3c0-1.1-.9-2-2-2zM7 7h10v3l4-4-4-4v3H5v6h2V7zm10 10H7v-3l-4 4 4 4v-3h12v-6h-2v4z" fill-rule="evenodd"/></svg> \ No newline at end of file
diff --git a/icons/settings-off.svg b/icons/settings-off.svg
new file mode 100644
index 0000000..4165162
--- /dev/null
+++ b/icons/settings-off.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M19.43 12.98c.04-.32.07-.64.07-.98 0-.34-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.09-.16-.26-.25-.44-.25-.06 0-.12.01-.17.03l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.06-.02-.12-.03-.18-.03-.17 0-.34.09-.43.25l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98 0 .33.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.09.16.26.25.44.25.06 0 .12-.01.17-.03l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.06.02.12.03.18.03.17 0 .34-.09.43-.25l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zm-1.98-1.71c.04.31.05.52.05.73 0 .21-.02.43-.05.73l-.14 1.13.89.7 1.08.84-.7 1.21-1.27-.51-1.04-.42-.9.68c-.43.32-.84.56-1.25.73l-1.06.43-.16 1.13-.2 1.35h-1.4l-.19-1.35-.16-1.13-1.06-.43c-.43-.18-.83-.41-1.23-.71l-.91-.7-1.06.43-1.27.51-.7-1.21 1.08-.84.89-.7-.14-1.13c-.03-.31-.05-.54-.05-.74s.02-.43.05-.73l.14-1.13-.89-.7-1.08-.84.7-1.21 1.27.51 1.04.42.9-.68c.43-.32.84-.56 1.25-.73l1.06-.43.16-1.13.2-1.35h1.39l.19 1.35.16 1.13 1.06.43c.43.18.83.41 1.23.71l.91.7 1.06-.43 1.27-.51.7 1.21-1.07.85-.89.7.14 1.13zM12 8c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 6c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"/></svg> \ No newline at end of file
diff --git a/icons/settings-on.svg b/icons/settings-on.svg
new file mode 100644
index 0000000..f53024e
--- /dev/null
+++ b/icons/settings-on.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><g><path d="M0,0h24v24H0V0z" fill="none"/><path d="M19.14,12.94c0.04-0.3,0.06-0.61,0.06-0.94c0-0.32-0.02-0.64-0.07-0.94l2.03-1.58c0.18-0.14,0.23-0.41,0.12-0.61 l-1.92-3.32c-0.12-0.22-0.37-0.29-0.59-0.22l-2.39,0.96c-0.5-0.38-1.03-0.7-1.62-0.94L14.4,2.81c-0.04-0.24-0.24-0.41-0.48-0.41 h-3.84c-0.24,0-0.43,0.17-0.47,0.41L9.25,5.35C8.66,5.59,8.12,5.92,7.63,6.29L5.24,5.33c-0.22-0.08-0.47,0-0.59,0.22L2.74,8.87 C2.62,9.08,2.66,9.34,2.86,9.48l2.03,1.58C4.84,11.36,4.8,11.69,4.8,12s0.02,0.64,0.07,0.94l-2.03,1.58 c-0.18,0.14-0.23,0.41-0.12,0.61l1.92,3.32c0.12,0.22,0.37,0.29,0.59,0.22l2.39-0.96c0.5,0.38,1.03,0.7,1.62,0.94l0.36,2.54 c0.05,0.24,0.24,0.41,0.48,0.41h3.84c0.24,0,0.44-0.17,0.47-0.41l0.36-2.54c0.59-0.24,1.13-0.56,1.62-0.94l2.39,0.96 c0.22,0.08,0.47,0,0.59-0.22l1.92-3.32c0.12-0.22,0.07-0.47-0.12-0.61L19.14,12.94z M12,15.6c-1.98,0-3.6-1.62-3.6-3.6 s1.62-3.6,3.6-3.6s3.6,1.62,3.6,3.6S13.98,15.6,12,15.6z"/></g></svg> \ No newline at end of file
diff --git a/icons/shuffle-off.svg b/icons/shuffle-off.svg
new file mode 100644
index 0000000..5bff963
--- /dev/null
+++ b/icons/shuffle-off.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0z" fill="none"/><path d="M10.59 9.17L5.41 4 4 5.41l5.17 5.17 1.42-1.41zM14.5 4l2.04 2.04L4 18.59 5.41 20 17.96 7.46 20 9.5V4h-5.5zm.33 9.41l-1.41 1.41 3.13 3.13L14.5 20H20v-5.5l-2.04 2.04-3.13-3.13z"/></svg> \ No newline at end of file
diff --git a/icons/shuffle-on.svg b/icons/shuffle-on.svg
new file mode 100644
index 0000000..77c33bd
--- /dev/null
+++ b/icons/shuffle-on.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M21 1H3c-1.1 0-2 .9-2 2v18c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V3c0-1.1-.9-2-2-2zM10.59 9.17L5.41 4 4 5.41l5.17 5.17 1.42-1.41zM14.5 4l2.04 2.04L4 18.59 5.41 20 17.96 7.46 20 9.5V4h-5.5zm.33 9.41l-1.41 1.41 3.13 3.13L14.5 20H20v-5.5l-2.04 2.04-3.13-3.13z" fill-rule="evenodd"/></svg> \ No newline at end of file
diff --git a/index.php b/index.php
new file mode 100644
index 0000000..f961cf2
--- /dev/null
+++ b/index.php
@@ -0,0 +1,218 @@
+<?php if (str_ends_with($_SERVER['HTTP_HOST'], ".familine.minteck.org")) { $_FAMILINE = true; } else { $_FAMILINE = false; } function l($en, $fr) { global $_FAMILINE; if ($_FAMILINE) { return $fr; } else { return $en; } } $root = $_SERVER['DOCUMENT_ROOT']; $root = $_SERVER['DOCUMENT_ROOT']; if ($_FAMILINE) { require_once "/mnt/familine/app/session.php"; } ?>
+<!DOCTYPE html>
+<html lang="en" style="overflow:hidden;">
+<head>
+ <meta charset="UTF-8">
+ <title><?= $_FAMILINE ? "Familine Musique" : "Argon" ?></title>
+ <link rel="shortcut icon" href="<?= l("/favicon.ico", "https://familine.minteck.org/icns/familine-music.svg") ?>" type="image/x-icon">
+ <link rel="stylesheet" href="/css/loader.css">
+ <link rel="stylesheet" href="/css/fonts.css">
+ <link rel="stylesheet" href="/css/general.css">
+ <link rel="stylesheet" href="/dark.css">
+ <meta name="HandheldFriendly" content="true" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
+ <script>
+ const AppName = "<?= $_FAMILINE ? "Familine Musique" : "Argon" ?>";
+ function l(en, fr) {
+ if (<?= $_FAMILINE ? "true" : "false" ?>) {
+ return fr;
+ } else {
+ return en;
+ }
+ }
+ </script>
+
+ <style>
+ #argon-loader {
+ position: fixed;
+ z-index: 9999;
+ inset: 0;
+ background-color: white;
+ }
+
+ #argon-loader-logo {
+ display: flex;
+ position: fixed;
+ align-items: center;
+ justify-content: center;
+ inset: 0;
+ }
+ </style>
+ <script>
+ const loadScript = src => {
+ return new Promise((resolve, reject) => {
+ const script = document.createElement('script')
+ script.type = 'text/javascript'
+ script.onload = resolve
+ script.onerror = reject
+ script.src = src
+ document.head.append(script)
+ })
+ }
+ const loadStyle = src => {
+ return new Promise((resolve, reject) => {
+ const link = document.createElement('link')
+ link.rel = 'stylesheet'
+ link.onload = resolve
+ link.onerror = reject
+ link.href = src
+ document.head.append(link)
+ })
+ }
+ const sleep = (delay) => new Promise((resolve) => setTimeout(resolve, delay))
+
+ _argonLoadedHooks = [];
+
+ window.onload = () => {
+ setTimeout(() => {
+ document.getElementById("argon-loader-message").innerText = l("Importing JavaScript files...", "Importation des fichiers JavaScript...");
+ if (window.electronAPI && window.electronAPI.affectMessage) window.electronAPI.affectMessage(document.getElementById("argon-loader-message").innerText);
+ window.fetch("/api/get_app_js.php").then(async (a) => {
+ a.text().then(async (b) => {
+ files = JSON.parse(b);
+ for (file of files) {
+ await sleep(100);
+ document.getElementById("argon-loader-message").innerText = l("Importing JavaScript files... ", "Importation des fichiers JavaScript... ") + file;
+ if (window.electronAPI && window.electronAPI.affectMessage) window.electronAPI.affectMessage(document.getElementById("argon-loader-message").innerText);
+ await loadScript(file + "?" + Math.random());
+ }
+ await sleep(100);
+ document.getElementById("argon-loader-message").innerText = l("Running JavaScript startup hooks...", "Exécution des modules JavaScript de démarrage...");
+ if (window.electronAPI && window.electronAPI.affectMessage) window.electronAPI.affectMessage(document.getElementById("argon-loader-message").innerText);
+ for (hook of _argonLoadedHooks) {
+ await sleep(100);
+ if (hook.name.trim() !== "") {
+ document.getElementById("argon-loader-message").innerText = l("Running JavaScript startup hooks... ", "Exécution des modules JavaScript de démarrage... ") + hook.name;
+ if (window.electronAPI && window.electronAPI.affectMessage) window.electronAPI.affectMessage(document.getElementById("argon-loader-message").innerText);
+ } else {
+ document.getElementById("argon-loader-message").innerText = l("Running JavaScript startup hooks... <!>", "Exécution des modules JavaScript de démarrage... <!>");
+ if (window.electronAPI && window.electronAPI.affectMessage) window.electronAPI.affectMessage(document.getElementById("argon-loader-message").innerText);
+ }
+ hook();
+ }
+ document.getElementById("argon-loader-message").innerText = l("Importing style definitions...", "Importation des définitions de style...");
+ if (window.electronAPI && window.electronAPI.affectMessage) window.electronAPI.affectMessage(document.getElementById("argon-loader-message").innerText);
+ window.fetch("/api/get_app_css.php").then(async (a) => {
+ a.text().then(async (b) => {
+ files = JSON.parse(b);
+ for (file of files) {
+ await sleep(100);
+ document.getElementById("argon-loader-message").innerText = l("Importing style definitions... ", "Importation des définitions de style... ") + file;
+ if (window.electronAPI && window.electronAPI.affectMessage) window.electronAPI.affectMessage(document.getElementById("argon-loader-message").innerText);
+ await loadStyle(file + "?" + Math.random());
+ }
+ await sleep(100);
+ document.getElementById("argon-loader-message").innerText = l("Resolving songs...", "Résolution des morceaux...");
+ if (window.electronAPI && window.electronAPI.affectMessage) window.electronAPI.affectMessage(document.getElementById("argon-loader-message").innerText);
+ window.fetch("/api/get_list.php").then(async (a) => {
+ a.text().then(async (b) => {
+ _argonSongsData = JSON.parse(b);
+ document.getElementById("argon-loader-message").innerText = l("Loading interface...", "Chargement de l'interface...");
+ if (window.electronAPI && window.electronAPI.affectMessage) window.electronAPI.affectMessage(document.getElementById("argon-loader-message").innerText);
+ document.getElementById("argon-loader").style.display = "none";
+ if (window.electronAPI.finishStartup) window.electronAPI.finishStartup();
+ })
+ })
+ })
+ })
+ })
+ })
+ }, 1000)
+ }
+ </script>
+</head>
+<body>
+ <?php if ($_FAMILINE): ?>
+ <iframe style="position:fixed;left:0;right:0;top:0;border: none;width: 100%;height:32px;" src="https://cdn.familine.minteck.org/statusbar.php"></iframe>
+ <style>
+ #argon-loader, #argon-app, #navigation-outer, #frame {
+ top: 32px;
+ }
+ </style>
+ <?php endif; ?>
+ <audio id="argon-player"></audio>
+ <div id="argon-loader">
+ <div id="argon-loader-logo">
+ <div style="text-align: center;">
+ <img src="<?= str_contains($_SERVER['HTTP_USER_AGENT'], "+AutomateCloud/") && !$_FAMILINE ? ("/native.svg") : ($_FAMILINE ? "https://familine.minteck.org/icns/familine-music.svg" : "/logo/256.png") ?>" style="width:128px;">
+ <br><br>
+ <div style="width:48px;height:48px;text-align: center;margin-left: auto;margin-right: auto;">
+ <svg class="circular-loader" viewBox="25 25 50 50">
+ <circle class="loader-path" cx="50" cy="50" r="20" fill="none"></circle>
+ </svg>
+ </div>
+ </div>
+ </div>
+ <div style="position: fixed;bottom: 10px;left: 10px;font-size:12px;">
+ <span id="argon-loader-message" style="font-family:-apple-system, 'Segoe UI', 'Ubuntu', sans-serif;"><?= l("Waiting for network...", "En attente de connexion réseau...") ?></span>
+ </div>
+ </div>
+ <div id="argon-app">
+ <aside id="navigation-outer">
+ <div id="navigation">
+ <a onclick="ArgonNavigation.about();" id="navigation-about" title="<?= $_FAMILINE ? "Familine Musique" : "Argon" ?> v<?= file_get_contents($root . "/version"); ?>">
+ <img id="navigation-about-icon" src="<?= str_contains($_SERVER['HTTP_USER_AGENT'], "+AutomateCloud/") && !$_FAMILINE ? ("/native.svg") : ($_FAMILINE ? "https://familine.minteck.org/icns/familine-music.svg" : "/logo/256.png") ?>" alt="<?= $_FAMILINE ? "Familine Musique" : "Argon" ?>" id="navigation-logo">
+ </a>
+ <a onclick="ArgonNavigation.home();" title="<?= l("Home", "Accueil") ?>" class="navigation-item" id="navigation-home">
+ <img src="/icons/home-off.svg" alt="<?= l("Home", "Accueil") ?>" class="navigation-item-icon"
+ id="navigation-home-icon">
+ </a>
+ <a onclick="ArgonNavigation.library();" title="<?= l("Library", "Bibliothèque") ?>" class="navigation-item" id="navigation-library">
+ <img src="/icons/library-off.svg" alt="<?= l("Library", "Bibliothèque") ?>" class="navigation-item-icon"
+ id="navigation-library-icon">
+ </a>
+ <a onclick="ArgonNavigation.lyrics();" title="<?= l("Lyrics", "Paroles") ?>" class="navigation-item" id="navigation-lyrics">
+ <img src="/icons/lyrics-off.svg" alt="<?= l("Lyrics", "Paroles") ?>" class="navigation-item-icon"
+ id="navigation-lyrics-icon">
+ </a>
+ <a onclick="ArgonNavigation.settings();" title="<?= l("Settings", "Préférences") ?>" class="navigation-item" id="navigation-settings">
+ <img src="/icons/settings-off.svg" alt="<?= l("Settings", "Préférences") ?>" class="navigation-item-icon"
+ id="navigation-settings-icon">
+ </a>
+ </div>
+ </aside>
+ <footer id="player">
+ <div id="player-inner">
+ <div id="player-buttons">
+ <div id="player-buttons-inner">
+ <a onclick="ArgonPlayer.previous();" class="player-button player-button-disabled" title="<?= l("Previous", "Précédent") ?>" id="player-button-previous">
+ <img src="/icons/previous.svg" alt="<?= l("Previous", "Précédent") ?>" class="player-button-icon" id="player-button-previous-icon">
+ </a><a onclick="ArgonPlayer._player.play();" class="player-button" title="<?= l("Play", "Lecture") ?>" id="player-button-play">
+ <img src="/icons/play.svg" alt="<?= l("Play", "Lecture") ?>" class="player-button-icon" id="player-button-play-icon">
+ </a><a onclick="ArgonPlayer._player.pause();" class="player-button" title="Pause" id="player-button-pause">
+ <img src="/icons/pause.svg" alt="Pause" class="player-button-icon" id="player-button-pause-icon">
+ </a><a class="player-button" title="<?= l("Loading", "Chargement") ?>..." id="player-button-load">
+ <div class="player-button-icon" id="player-button-load-icon">
+ <svg class="circular-loader" viewBox="25 25 50 50">
+ <circle class="loader-path" cx="50" cy="50" r="20" fill="none"></circle>
+ </svg>
+ </div>
+ </a><a onclick="ArgonPlayer.next();" class="player-button player-button-disabled" title="<?= l("Next", "Suivant") ?>" id="player-button-next">
+ <img src="/icons/next.svg" alt="<?= l("Next", "Suivant") ?>" class="player-button-icon" id="player-button-next-icon">
+ </a><a onclick="ArgonPlayer.shuffle();" class="player-button" title="<?= l("Shuffle", "Lecture aléatoire") ?>" id="player-button-shuffle">
+ <img src="/icons/shuffle-off.svg" alt="<?= l("Shuffle", "Lecture aléatoire") ?>" class="player-button-icon" id="player-button-shuffle-icon">
+ </a><a onclick="ArgonPlayer.repeat();" class="player-button" title="<?= l("Repeat", "Lecture en boucle") ?>" id="player-button-repeat">
+ <img src="/icons/repeat-off.svg" alt="<?= l("Repeat", "Lecture en boucle") ?>" class="player-button-icon" id="player-button-repeat-icon">
+ </a>
+ </div>
+ </div>
+ <div id="player-seekbar-area">
+ <span id="player-seekbar-elapsed">00:00</span>
+ <input type="range" min="0" max="0" value="0" id="player-seekbar">
+ <span id="player-seekbar-total">00:00</span>
+ </div>
+ <div id="player-info">
+ <img id="player-artwork" alt="" src="">
+ <div id="player-info-text">
+ <div id="player-info-text-title">Promises</div>
+ <div id="player-info-text-set">Scootaloo EP</div>
+ </div>
+ </div>
+ </div>
+ </footer>
+ <main id="frame">
+ <iframe id="frame-inner"></iframe>
+ </main>
+ </div>
+</body>
+</html> \ No newline at end of file
diff --git a/js/frame.js b/js/frame.js
new file mode 100644
index 0000000..6f26e16
--- /dev/null
+++ b/js/frame.js
@@ -0,0 +1,25 @@
+_argonLoadedHooks.push(function ArgonStartupFrame() {
+ try {
+ log("Processing initial hash");
+ original = location.hash.substring(1);
+ document.getElementById("frame-inner").src = "/_frame" + original;
+ } catch (e) {
+ console.error(e);
+ location.hash = "";
+ }
+
+ window.addEventListener('hashchange', () => {
+ log("Processing hash change");
+ try {
+ original = location.hash.substring(1);
+ document.getElementById("frame-inner").src = "/_frame" + original;
+ } catch (e) {
+ console.error(e);
+ }
+ });
+
+ document.getElementById("frame-inner").addEventListener('load', () => {
+ log("Changing hash as per iframe URL");
+ location.hash = document.getElementById("frame-inner").contentDocument.location.href.split(location.host)[1].substring(7);
+ })
+}) \ No newline at end of file
diff --git a/js/logging.js b/js/logging.js
new file mode 100644
index 0000000..86a96a3
--- /dev/null
+++ b/js/logging.js
@@ -0,0 +1,3 @@
+function log(message) {
+ console.log('%c[' + new Date().toISOString() + "]%c " + message, 'font-family: monospace; background: rgba(0, 0, 0);', 'opacity: 1;');
+} \ No newline at end of file
diff --git a/js/navigation.js b/js/navigation.js
new file mode 100644
index 0000000..acab550
--- /dev/null
+++ b/js/navigation.js
@@ -0,0 +1,41 @@
+_argonLoadedHooks.push(function ArgonStartupNavigation() {
+ ArgonNavigation = {
+ home: () => {
+ document.getElementById("frame-inner").contentWindow.location.href = "/_frame/home";
+ },
+ library: () => {
+ document.getElementById("frame-inner").contentWindow.location.href = "/_frame/library";
+ },
+ lyrics: () => {
+ document.getElementById("frame-inner").contentWindow.location.href = "/_frame/lyrics";
+ },
+ settings: () => {
+ document.getElementById("frame-inner").contentWindow.location.href = "/_frame/settings";
+ },
+ about: () => {
+ document.getElementById("frame-inner").contentWindow.location.href = "/_frame/about";
+ },
+ }
+
+ setInterval(() => {
+ path = document.getElementById("frame-inner").contentWindow.location.pathname.substring(7);
+
+ document.getElementById("navigation-home-icon").src = "/icons/home-off.svg";
+ document.getElementById("navigation-library-icon").src = "/icons/library-off.svg";
+ document.getElementById("navigation-lyrics-icon").src = "/icons/lyrics-off.svg";
+ document.getElementById("navigation-settings-icon").src = "/icons/settings-off.svg";
+ document.getElementById("navigation-about-icon").style.filter = "";
+
+ if (path.startsWith("/home")) {
+ document.getElementById("navigation-home-icon").src = "/icons/home-on.svg";
+ } else if (path.startsWith("/library")) {
+ document.getElementById("navigation-library-icon").src = "/icons/library-on.svg";
+ } else if (path.startsWith("/lyrics")) {
+ document.getElementById("navigation-lyrics-icon").src = "/icons/lyrics-on.svg";
+ } else if (path.startsWith("/settings")) {
+ document.getElementById("navigation-settings-icon").src = "/icons/settings-on.svg";
+ } else if (path.startsWith("/about")) {
+ document.getElementById("navigation-about-icon").style.filter = "brightness(200%)";
+ }
+ })
+}) \ No newline at end of file
diff --git a/js/player.js b/js/player.js
new file mode 100644
index 0000000..2c73333
--- /dev/null
+++ b/js/player.js
@@ -0,0 +1,255 @@
+_argonLoadedHooks.push(function ArgonStartupPlayer() {
+ ArgonPlayer = {
+ _player: document.getElementById("argon-player"),
+ _current: null,
+ _seekbar: true,
+ _shuffle: false,
+ _repeat: false,
+ _endTriggered: false,
+ _preferredQualityRaw: "0",
+ _preferredQualityPreference: ["0"],
+ _currentQuality: null,
+ _qualityChangeTime: 0,
+ _qualityGoingDown: false,
+
+ _end: () => {
+ if (ArgonPlayer._endTriggered) return;
+
+ if (!ArgonPlayer._player.paused) {
+ ArgonPlayer._endTriggered = true;
+
+ if (ArgonPlayer._repeat) {
+ ArgonPlayer._player.currentTime = 0;
+ ArgonPlayer._player.play().catch(e => {
+ console.error(e);
+ alert("An error occurred while trying to play this song. Please try again later.");
+ }).then(() => {
+ ArgonPlayer._endTriggered = false;
+ });
+ } else {
+ ArgonPlayer.next();
+ }
+ }
+ },
+
+ _qualityDown: () => {
+ if (ArgonPlayer._qualityGoingDown) return;
+ ArgonPlayer._qualityGoingDown = true;
+
+ if (ArgonPlayer._currentQuality === "high") {
+ ArgonPlayer._setQualityTo("medium");
+ } else if (ArgonPlayer._currentQuality === "medium") {
+ ArgonPlayer._setQualityTo("low");
+ } else if (ArgonPlayer._currentQuality === "low") {
+ ArgonPlayer._setQualityTo("verylow");
+ } else if (ArgonPlayer._currentQuality === "verylow") {
+ ArgonPlayer._setQualityTo("ultralow");
+ } else if (ArgonPlayer._currentQuality === "ultralow") {
+ ArgonPlayer._setQualityTo("superlow");
+ } else {
+ log("Quality is already as low as possible");
+ }
+ },
+
+ _setQualityTo: (quality) => {
+ log("Resolving track " + ArgonPlayer._current + "...");
+ ArgonPlayer._qualityChangeTime = ArgonPlayer._player.currentTime;
+ window.fetch("/api/get_audio_files.php?_=" + ArgonPlayer._current).then((a) => {
+ a.text().then((b) => {
+ let data = JSON.parse(b);
+ ArgonPlayer._currentQuality = quality;
+ ArgonPlayer._player.src = data[ArgonPlayer._currentQuality];
+ log("Playing " + ArgonPlayer._current);
+ ArgonPlayer._player.play().catch(e => {
+ console.error(e);
+ alert("An error occurred while trying to play this song. Please try again later.");
+ }).then(() => {
+ ArgonPlayer._player.currentTime = ArgonPlayer._qualityChangeTime;
+ ArgonPlayer._endTriggered = false;
+ ArgonPlayer._qualityGoingDown = false;
+ });
+ });
+ });
+ },
+
+ play: (song) => {
+ ArgonPlayer._current = song;
+ document.getElementById("player-artwork").src = "";
+
+ document.getElementById("player-artwork").src = "/api/get_image.php?_=" + ArgonPlayer._current;
+ document.getElementById("player-info-text-title").innerHTML = "<a id='frame-viewer-header-text-linkToOriginal' onclick='document.getElementById(&quot;frame-inner&quot;).contentDocument.location.href=&quot;/_frame/library/" + ArgonPlayer._current + "&quot;'>" + _argonSongsData.songs[ArgonPlayer._current].name.replaceAll(">", "&gt;") + "</a>";
+ if (_argonSongsData.songs[ArgonPlayer._current].set !== null && _argonSongsData.songs[ArgonPlayer._current].set !== undefined) {
+ document.getElementById("player-info-text-set").innerHTML = _argonSongsData.songs[ArgonPlayer._current].author.replaceAll("<", "&lt;").replaceAll(">", "&gt;") + " · <a id='frame-viewer-header-text-linkToSet' onclick='document.getElementById(&quot;frame-inner&quot;).contentDocument.location.href=&quot;/_frame/library/" + _argonSongsData.songs[ArgonPlayer._current].set._id + "&quot;'>" + _argonSongsData.songs[ArgonPlayer._current].set.name.replaceAll("<", "&lt;").replaceAll(">", "&gt;") + "</a> · " + _argonSongsData.songs[ArgonPlayer._current].release.substring(0, 4).replaceAll("<", "&lt;").replaceAll(">", "&gt;");
+ } else {
+ document.getElementById("player-info-text-set").innerText = _argonSongsData.songs[ArgonPlayer._current].author + " · " + _argonSongsData.songs[ArgonPlayer._current].release.substring(0, 4);
+ }
+
+ log("Resolving track " + song + "...");
+ window.fetch("/api/get_audio_files.php?_=" + song).then((a) => {
+ a.text().then((b) => {
+ let data = JSON.parse(b);
+ if (ArgonPlayer._preferredQualityPreference[0] === "2") {
+ ArgonPlayer._currentQuality = "originalpcm";
+ } else if (ArgonPlayer._preferredQualityPreference[0] === "0") {
+ ArgonPlayer._currentQuality = "high";
+ } else {
+ ArgonPlayer._currentQuality = ArgonPlayer._preferredQualityPreference[1];
+ }
+ ArgonPlayer._player.src = data[ArgonPlayer._currentQuality];
+ log("Playing " + song);
+ ArgonPlayer._player.play().catch(e => {
+ if (e.name !== "DOMException") {
+ console.error(e);
+ alert("An error occurred while trying to play this song. Please try again later.");
+ }
+ }).then(() => {
+ ArgonPlayer._endTriggered = false;
+ });
+ });
+ });
+ },
+
+ shuffle: () => {
+ ArgonPlayer._shuffle = !ArgonPlayer._shuffle;
+
+ if (ArgonPlayer._shuffle) {
+ document.getElementById("player-button-shuffle-icon").src = "/icons/shuffle-on.svg";
+ } else {
+ document.getElementById("player-button-shuffle-icon").src = "/icons/shuffle-off.svg";
+ }
+ },
+
+ repeat: () => {
+ ArgonPlayer._repeat = !ArgonPlayer._repeat;
+
+ if (ArgonPlayer._repeat) {
+ document.getElementById("player-button-repeat-icon").src = "/icons/repeat-on.svg";
+ } else {
+ document.getElementById("player-button-repeat-icon").src = "/icons/repeat-off.svg";
+ }
+ },
+
+ _controls: () => {
+ ArgonPlayer._preferredQualityRaw = localStorage.getItem("quality") ?? "0";
+ ArgonPlayer._preferredQualityPreference = (localStorage.getItem("quality") ?? localStorage.getItem("quality") ?? "0").split(":");
+
+ if (ArgonPlayer._current !== null) {
+ document.getElementById("player-inner").style.display = "";
+
+ if (!ArgonPlayer._player.paused) {
+ if (_argonSongsData.songs[ArgonPlayer._current].original !== null) {
+ document.title = _argonSongsData.songs[ArgonPlayer._current].author + " - " + _argonSongsData.songs[ArgonPlayer._current].name + " (" + _argonSongsData.songs[ArgonPlayer._current].original + " cover)";
+ } else {
+ document.title = _argonSongsData.songs[ArgonPlayer._current].author + " - " + _argonSongsData.songs[ArgonPlayer._current].name
+ }
+ } else {
+ document.title = AppName;
+ }
+
+ if (ArgonPlayer._player.currentTime >= ArgonPlayer._player.duration) {
+ ArgonPlayer._end();
+ }
+
+ if (ArgonPlayer._player.readyState === 0) {
+ document.getElementById("player-button-load").style.display = "";
+ document.getElementById("player-button-pause").style.display = "none";
+ document.getElementById("player-button-play").style.display = "none";
+ document.getElementById("player-seekbar").disabled = true;
+
+ document.getElementById("player-seekbar-elapsed").innerText = "-:--";
+ document.getElementById("player-seekbar-total").innerText = "-:--";
+ } else {
+ document.getElementById("player-seekbar").disabled = false;
+
+ if (ArgonPlayer._repeat) {
+ ArgonPlayer._player.loop = true;
+ }
+
+ if (ArgonPlayer._player.paused) {
+ document.getElementById("player-button-play").style.display = "";
+ document.getElementById("player-button-pause").style.display = "none";
+ document.getElementById("player-button-load").style.display = "none";
+ } else {
+ document.getElementById("player-button-pause").style.display = "";
+ document.getElementById("player-button-play").style.display = "none";
+ document.getElementById("player-button-load").style.display = "none";
+ }
+
+ if (!ArgonPlayer._shuffle) {
+ if (_argonSongsData.sorted[_argonSongsData.sorted.indexOf(ArgonPlayer._current) + 1]) {
+ document.getElementById("player-button-next").classList.remove("player-button-disabled");
+ } else {
+ document.getElementById("player-button-next").classList.add("player-button-disabled");
+ }
+
+ if (_argonSongsData.sorted[_argonSongsData.sorted.indexOf(ArgonPlayer._current) - 1]) {
+ document.getElementById("player-button-previous").classList.remove("player-button-disabled");
+ } else {
+ document.getElementById("player-button-previous").classList.add("player-button-disabled");
+ }
+ } else {
+ document.getElementById("player-button-previous").classList.remove("player-button-disabled");
+ document.getElementById("player-button-next").classList.remove("player-button-disabled");
+ }
+
+ let current;
+ let total;
+ if (ArgonPlayer._player.duration >= 600) {
+ current = new Date(ArgonPlayer._player.currentTime * 1000).toISOString().substr(14, 5);
+ total = new Date(ArgonPlayer._player.duration * 1000).toISOString().substr(14, 5);
+ } else {
+ current = new Date(ArgonPlayer._player.currentTime * 1000).toISOString().substr(15, 4);
+ total = new Date(ArgonPlayer._player.duration * 1000).toISOString().substr(15, 4);
+ }
+
+ document.getElementById("player-seekbar-elapsed").innerText = current;
+ document.getElementById("player-seekbar-total").innerText = total;
+ }
+
+ if (ArgonPlayer._seekbar) {
+ document.getElementById("player-seekbar").max = ArgonPlayer._player.duration * 1000;
+ document.getElementById("player-seekbar").value = ArgonPlayer._player.currentTime * 1000;
+ }
+ } else {
+ document.title = AppName;
+ document.getElementById("player-inner").style.display = "none";
+ }
+ },
+
+ next: () => {
+ if (!ArgonPlayer._shuffle) {
+ if (_argonSongsData.sorted[_argonSongsData.sorted.indexOf(ArgonPlayer._current) + 1]) {
+ ArgonPlayer.play(_argonSongsData.sorted[_argonSongsData.sorted.indexOf(ArgonPlayer._current) + 1]);
+ }
+ } else {
+ items = _argonSongsData.sorted.filter(i => i !== ArgonPlayer._current)
+ ArgonPlayer.play(items[Math.floor(Math.random() * items.length)]);
+ }
+ },
+
+ previous: () => {
+ if (!ArgonPlayer._shuffle) {
+ if (_argonSongsData.sorted[_argonSongsData.sorted.indexOf(ArgonPlayer._current) - 1]) {
+ ArgonPlayer.play(_argonSongsData.sorted[_argonSongsData.sorted.indexOf(ArgonPlayer._current) - 1]);
+ }
+ } else {
+ items = _argonSongsData.sorted.filter(i => i !== ArgonPlayer._current)
+ ArgonPlayer.play(items[Math.floor(Math.random() * items.length)]);
+ }
+ }
+ }
+
+ setInterval(ArgonPlayer._controls);
+ setInterval(() => {
+ if (ArgonPlayer._current !== null) {
+ if (ArgonPlayer._player.readyState <= 2) {
+ if (ArgonPlayer._preferredQualityPreference[0] === "0") {
+ log("Quality is too high for network, reducing quality...");
+ ArgonPlayer._qualityDown()
+ } else {
+ log("Quality is too high for network, settings does not allow reducing quality.");
+ }
+ }
+ }
+ }, 10000)
+}) \ No newline at end of file
diff --git a/js/seekbar.js b/js/seekbar.js
new file mode 100644
index 0000000..afeb745
--- /dev/null
+++ b/js/seekbar.js
@@ -0,0 +1,29 @@
+_argonLoadedHooks.push(function ArgonStartupSeekbar() {
+ document.getElementById("player-seekbar").addEventListener('mousedown', () => {
+ log("Started seeking");
+ ArgonPlayer._seekbar = false;
+ });
+
+ document.getElementById("player-seekbar").addEventListener('mouseup', () => {
+ log("Stopped seeking");
+ ArgonPlayer._player.currentTime = document.getElementById("player-seekbar").value / 1000;
+ ArgonPlayer._seekbar = true;
+ });
+
+ document.getElementById("player-seekbar").addEventListener('touchstart', () => {
+ log("Started seeking");
+ ArgonPlayer._seekbar = false;
+ });
+
+ document.getElementById("player-seekbar").addEventListener('touchend', () => {
+ log("Stopped seeking");
+ ArgonPlayer._player.currentTime = document.getElementById("player-seekbar").value / 1000;
+ ArgonPlayer._seekbar = true;
+ });
+
+ document.getElementById("player-seekbar").addEventListener('touchcancel', () => {
+ log("Stopped seeking");
+ ArgonPlayer._player.currentTime = document.getElementById("player-seekbar").value / 1000;
+ ArgonPlayer._seekbar = true;
+ });
+}) \ No newline at end of file
diff --git a/logo/.DS_Store b/logo/.DS_Store
new file mode 100644
index 0000000..5008ddf
--- /dev/null
+++ b/logo/.DS_Store
Binary files differ
diff --git a/logo/128.png b/logo/128.png
new file mode 100644
index 0000000..94fa615
--- /dev/null
+++ b/logo/128.png
Binary files differ
diff --git a/logo/24.png b/logo/24.png
new file mode 100644
index 0000000..cc9a930
--- /dev/null
+++ b/logo/24.png
Binary files differ
diff --git a/logo/256.png b/logo/256.png
new file mode 100644
index 0000000..1dfc4e3
--- /dev/null
+++ b/logo/256.png
Binary files differ
diff --git a/logo/32.png b/logo/32.png
new file mode 100644
index 0000000..65250c1
--- /dev/null
+++ b/logo/32.png
Binary files differ
diff --git a/logo/48.png b/logo/48.png
new file mode 100644
index 0000000..37de72d
--- /dev/null
+++ b/logo/48.png
Binary files differ
diff --git a/logo/512.png b/logo/512.png
new file mode 100644
index 0000000..24f2568
--- /dev/null
+++ b/logo/512.png
Binary files differ
diff --git a/logo/56.png b/logo/56.png
new file mode 100644
index 0000000..ebddf5b
--- /dev/null
+++ b/logo/56.png
Binary files differ
diff --git a/logo/64.png b/logo/64.png
new file mode 100644
index 0000000..b2b87c5
--- /dev/null
+++ b/logo/64.png
Binary files differ
diff --git a/native.svg b/native.svg
new file mode 100644
index 0000000..31565d8
--- /dev/null
+++ b/native.svg
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 25.3.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ viewBox="0 0 96 93.6" style="enable-background:new 0 0 96 93.6;" xml:space="preserve">
+<style type="text/css">
+ .st0{fill:#75AEE6;}
+ .st1{fill:#1A2733;}
+ .st2{display:none;}
+ .st3{display:inline;fill:#FFFFFF;}
+ .st4{display:inline;opacity:0.15;}
+ .st5{fill:#00C8FF;}
+ .st6{fill:#CFDBE6;}
+ .st7{fill:none;}
+</style>
+ <title>Photoshop_1</title>
+ <path class="st0" d="M23.1,9.1H73c8,0,14.4,6.3,14.4,14.1v46.9C87.4,78,81,84.4,73,84.4H23.1c-8,0-14.4-6.3-14.4-14.1V23.3
+ C8.7,15.5,15.1,9.1,23.1,9.1z"/>
+ <path class="st1" d="M23.8,12.3h48.6c6.5,0,11.8,5.2,11.8,11.6v45.7c0,6.4-5.3,11.6-11.8,11.6H23.8C17.3,81.1,12,76,12,69.6V23.9
+ C12,17.5,17.3,12.3,23.8,12.3z"/>
+ <g class="st2">
+ <path class="st3" d="M28.1,27.4c0-0.3,0.5-0.4,0.8-0.4c2.1-0.1,5.2-0.1,8.4-0.1c9,0,12.6,4.9,12.6,11.2c0,8.2-6,11.7-13.5,11.7
+ h-2.5v12.3c0,0.2-0.1,0.4-0.3,0.4c0,0-0.1,0-0.1,0h-5.2c-0.2,0-0.4-0.1-0.4-0.3c0,0,0-0.1,0-0.1L28.1,27.4z M33.8,44.5h2.6
+ c3.8,0,7.5-1.3,7.5-6.4c0-4.1-2.6-6.2-7-6.2c-1.1,0-2.1,0-3.1,0.1V44.5z M62.1,40.6c-2.6,0-3.4,1.3-3.4,2.3s0.7,1.9,4.1,3.7
+ c5.1,2.4,6.8,4.8,6.8,8.2c0,5.1-3.9,8-9.4,8c-2.4,0.1-4.7-0.4-6.8-1.4C53,61.3,53,61.2,53,61v-4.8c0-0.3,0.1-0.4,0.4-0.3
+ c1.9,1.3,4.2,1.9,6.6,1.9c2.6,0,3.7-1,3.7-2.4c0-1.2-0.8-2.2-4.1-3.9C55,49.4,53,47.2,53,43.5c0-4.1,3.3-7.6,9-7.6
+ c2-0.1,4,0.2,5.9,0.9c0.2,0.1,0.4,0.4,0.3,0.6c0,0,0,0,0,0v4.4c0,0.3-0.1,0.4-0.5,0.3C66,41.2,64,40.7,62.1,40.6L62.1,40.6z"/>
+ <g class="st4">
+ <path class="st5" d="M28.1,27.4c0-0.3,0.5-0.4,0.8-0.4c2.1-0.1,5.2-0.1,8.4-0.1c9,0,12.6,4.9,12.6,11.2c0,8.2-6,11.7-13.5,11.7
+ h-2.5v12.3c0,0.2-0.1,0.4-0.3,0.4c0,0-0.1,0-0.1,0h-5.2c-0.2,0-0.4-0.1-0.4-0.3c0,0,0-0.1,0-0.1L28.1,27.4z M33.8,44.5h2.6
+ c3.8,0,7.5-1.3,7.5-6.4c0-4.1-2.6-6.2-7-6.2c-1.1,0-2.1,0-3.1,0.1V44.5z M62.1,40.6c-2.6,0-3.4,1.3-3.4,2.3s0.7,1.9,4.1,3.7
+ c5.1,2.4,6.8,4.8,6.8,8.2c0,5.1-3.9,8-9.4,8c-2.4,0.1-4.7-0.4-6.8-1.4C53,61.3,53,61.2,53,61v-4.8c0-0.3,0.1-0.4,0.4-0.3
+ c1.9,1.3,4.2,1.9,6.6,1.9c2.6,0,3.7-1,3.7-2.4c0-1.2-0.8-2.2-4.1-3.9C55,49.4,53,47.2,53,43.5c0-4.1,3.3-7.6,9-7.6
+ c2-0.1,4,0.2,5.9,0.9c0.2,0.1,0.4,0.4,0.3,0.6c0,0,0,0,0,0v4.4c0,0.3-0.1,0.4-0.5,0.3C66,41.2,64,40.7,62.1,40.6L62.1,40.6z"/>
+ </g>
+</g>
+ <g>
+ <path class="st6" d="M30.8,53.1l-2.7,9.3c0,0.3-0.2,0.4-0.5,0.4h-4.6c-0.3,0-0.4-0.2-0.3-0.5l9.8-31.7c0.1-0.5,0.3-1,0.3-2.8
+ c0-0.2,0.1-0.3,0.3-0.3h6.4c0.2,0,0.3,0.1,0.3,0.3l10.8,34.6c0.1,0.3,0,0.4-0.2,0.4h-5.1c-0.2,0-0.3-0.1-0.4-0.3l-2.8-9.3H30.8z
+ M40.6,47.6c-1-3.6-3.3-11.2-4.2-15h0c-0.8,3.6-2.6,9.9-4.1,15H40.6z"/>
+ <path class="st6" d="M60.6,53.5c-0.2,0.5-0.2,1.1-0.2,1.7c0.1,0.6,0.3,1.2,0.7,1.7l4.8,0.3c6.6,0.3,9.5,3.2,9.5,7.5
+ c0,5.4-4.8,9.8-12.1,9.8c-7.6,0-11.2-4.3-11.2-8.2c0-1.7,1.3-3.9,4.6-7c-0.7-1.2-1.1-2.5-1.1-4c0-1.2,0.3-2.5,0.9-3.6
+ c-2-1.5-3.3-3.7-3.3-7c0-5.1,3.5-9.2,9.4-9.2c1.6,0,3.1,0.2,4.1,0.4c0.4,0.1,0.8,0.2,1.1,0.2h6.7c0.2,0,0.3,0.1,0.3,0.3v4.2
+ c0,0.3-0.1,0.4-0.3,0.4c-1,0-2.7-0.1-3.8-0.3c0.6,0.9,1.1,2.2,1.1,4.2c0,5.9-4.2,8.7-9.2,8.7C61.9,53.7,61.2,53.6,60.6,53.5z
+ M64.6,62.4l-5-0.3c-1.4,1.1-2.4,2.9-2.4,3.7c0,2,2.3,4.1,6.3,4.1c4.7,0,6.7-2.1,6.7-4.3C70.2,63.2,67.8,62.5,64.6,62.4z
+ M62.5,40.1c-2.4,0-4,1.8-4,4.6c0,2.6,1.4,4.5,4,4.5c2.5,0,4-1.7,4-4.4C66.4,42.2,65.2,40.1,62.5,40.1z"/>
+</g>
+ <rect class="st7" width="96" height="93.6"/>
+</svg>
diff --git a/transparent.png b/transparent.png
new file mode 100644
index 0000000..cf0994c
--- /dev/null
+++ b/transparent.png
Binary files differ
diff --git a/version b/version
new file mode 100644
index 0000000..dc2b74e
--- /dev/null
+++ b/version
@@ -0,0 +1 @@
+0.5.7 \ No newline at end of file