]> OzVa Git service - critters-api/commitdiff
Visual changes to player
authorMax Value <greenwoodw50@gmail.com>
Fri, 3 Jan 2025 20:55:00 +0000 (20:55 +0000)
committerMax Value <greenwoodw50@gmail.com>
Fri, 3 Jan 2025 21:13:40 +0000 (21:13 +0000)
+ added pallet
+ added pallet to homepage
+ added requirement.txt
- visual changes to player
- changes to play and pause button
- changes to todo

critters.py
requirements.txt [new file with mode: 0644]
static/pallet.html [new file with mode: 0644]
static/pause.svg
static/play.svg
static/player.html
static/style.css
templates/home.html

index 943ae459268a9e71f6504e3ce87fc7e1967de44e..33cdfe0fb4255aaa41fa37959b81fe636f546ca1 100755 (executable)
@@ -1,4 +1,4 @@
-#! .venv/bin/python3
+#!.venv/bin/python3
 
 from flask import Flask, Response, request, render_template_string, redirect, send_from_directory, url_for
 from flask_httpauth import HTTPBasicAuth
diff --git a/requirements.txt b/requirements.txt
new file mode 100644 (file)
index 0000000..22fdb90
--- /dev/null
@@ -0,0 +1,3 @@
+flask
+flask_httpauth
+werkzeug
diff --git a/static/pallet.html b/static/pallet.html
new file mode 100644 (file)
index 0000000..d20eac7
--- /dev/null
@@ -0,0 +1,44 @@
+<html>
+    <head>
+        <style>
+div {
+    display: inline-block;
+    width: 100px;
+    height: 100px;
+}
+#one {
+    background-color: var(--background);
+    color: white;
+}
+#two {
+    background-color: var(--dark);
+    color: white;
+}
+#three {
+    background-color: var(--primary);
+    color: black;
+}
+#four {
+    background-color: var(--off-primary);
+    color: black;
+}
+#five {
+    background-color: var(--secondary);
+    color: black;
+}
+#six {
+    background-color: var(--tertiary);
+    color: white;
+}
+        </style>
+        <link rel="stylesheet" href="/static/style.css">
+    </head>
+    <body>
+        <div id="one">Background</div>
+        <div id="two">Dark</div>
+        <div id="three">Primary</div>
+        <div id="four">Off-primary</div>
+        <div id="five">Secondary</div>
+        <div id="six">Tertiary</div>
+    </body>
+</html>
index d48e26595944a394a9a0f5575bcb23306030e6e8..5d6e3affb43e669921b40b4775e447978af2e1a1 100644 (file)
@@ -6,9 +6,58 @@
    version="1.1"
    xml:space="preserve"
    id="SVGRoot"
+   sodipodi:docname="pause.svg"
+   inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
    xmlns="http://www.w3.org/2000/svg"
-   xmlns:svg="http://www.w3.org/2000/svg"><defs
-   id="defs9" />
+   xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
+   id="namedview1"
+   pagecolor="#ffffff"
+   bordercolor="#000000"
+   borderopacity="0.25"
+   inkscape:showpageshadow="2"
+   inkscape:pageopacity="0.0"
+   inkscape:pagecheckerboard="true"
+   inkscape:deskcolor="#d1d1d1"
+   inkscape:zoom="0.64135202"
+   inkscape:cx="413.96923"
+   inkscape:cy="477.11708"
+   inkscape:window-width="1366"
+   inkscape:window-height="740"
+   inkscape:window-x="0"
+   inkscape:window-y="0"
+   inkscape:window-maximized="1"
+   inkscape:current-layer="SVGRoot"
+   inkscape:document-units="px"
+   showguides="true"><sodipodi:guide
+     position="499.98375,534.4491"
+     orientation="1,0"
+     id="guide1"
+     inkscape:locked="false" /><sodipodi:guide
+     position="493.69464,500.01625"
+     orientation="0,-1"
+     id="guide2"
+     inkscape:locked="false" /></sodipodi:namedview><defs
+   id="defs9"><linearGradient
+     id="linearGradient3"
+     inkscape:collect="always"><stop
+       style="stop-color:#70b783;stop-opacity:1;"
+       offset="0.25"
+       id="stop3" /><stop
+       style="stop-color:#ffffff;stop-opacity:0;"
+       offset="1"
+       id="stop4" /></linearGradient><radialGradient
+     inkscape:collect="always"
+     xlink:href="#linearGradient3"
+     id="radialGradient4"
+     cx="500"
+     cy="500"
+     fx="500"
+     fy="500"
+     r="500"
+     gradientUnits="userSpaceOnUse" /></defs>
 
 <style
    type="text/css"
@@ -23,11 +72,13 @@ g.prefab path {
 }
 </style>
 
-<path
+<rect
+   style="vector-effect:non-scaling-stroke;fill:url(#radialGradient4);fill-opacity:1;stroke:none;stroke-opacity:1;-inkscape-stroke:hairline"
+   id="rect3"
+   width="1000"
+   height="1000"
+   x="0"
+   y="0" /><path
    id="rect10"
-   style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:3;stroke-dasharray:none;stroke-opacity:1"
-   d="M 300,250 H 450 V 750 H 300 Z m 250,0 H 700 V 750 H 550 Z" /><path
-   style="display:none;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:3;stroke-dasharray:none;stroke-opacity:1"
-   id="path10"
-   d="M 800,500 574.99999,629.90381 350,759.80762 l 0,-259.80763 0,-259.80761 225.00001,129.90381 z"
-   transform="translate(-50)" /></svg>
+   style="fill:#121212;fill-opacity:1;stroke:none;stroke-width:3;stroke-dasharray:none;stroke-opacity:1"
+   d="M 360,325 H 465 V 675 H 360 Z m 175,0 H 640 V 675 H 535 Z" /></svg>
index 7ba594004cc6aee792bb1d5d962bb359622fa573..8afefbc8b3ebf9c9e9aa5195a59490404bbd6572 100644 (file)
@@ -6,9 +6,57 @@
    version="1.1"
    xml:space="preserve"
    id="SVGRoot"
+   sodipodi:docname="play.svg"
+   inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
    xmlns="http://www.w3.org/2000/svg"
-   xmlns:svg="http://www.w3.org/2000/svg"><defs
-   id="defs9" />
+   xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
+   id="namedview1"
+   pagecolor="#ffffff"
+   bordercolor="#000000"
+   borderopacity="0.25"
+   inkscape:showpageshadow="2"
+   inkscape:pageopacity="0.0"
+   inkscape:pagecheckerboard="0"
+   inkscape:deskcolor="#d1d1d1"
+   inkscape:zoom="0.6958339"
+   inkscape:cx="518.80197"
+   inkscape:cy="444.0715"
+   inkscape:window-width="1366"
+   inkscape:window-height="740"
+   inkscape:window-x="0"
+   inkscape:window-y="0"
+   inkscape:window-maximized="1"
+   inkscape:current-layer="SVGRoot"
+   showguides="true"><sodipodi:guide
+     position="499.98971,554.31523"
+     orientation="1,0"
+     id="guide2"
+     inkscape:locked="false" /><sodipodi:guide
+     position="478.22102,500.16673"
+     orientation="0,-1"
+     id="guide3"
+     inkscape:locked="false" /></sodipodi:namedview><defs
+   id="defs9"><radialGradient
+     inkscape:collect="always"
+     xlink:href="#linearGradient3"
+     id="radialGradient4"
+     cx="500"
+     cy="500"
+     fx="500"
+     fy="500"
+     r="500"
+     gradientUnits="userSpaceOnUse" /><linearGradient
+     id="linearGradient3"
+     inkscape:collect="always"><stop
+       style="stop-color:#70b783;stop-opacity:1;"
+       offset="0.25"
+       id="stop3" /><stop
+       style="stop-color:#ffffff;stop-opacity:0;"
+       offset="1"
+       id="stop4" /></linearGradient></defs>
 
 <style
    type="text/css"
@@ -23,11 +71,13 @@ g.prefab path {
 }
 </style>
 
-<path
-   id="rect10"
-   style="display:none;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:3;stroke-dasharray:none;stroke-opacity:1"
-   d="M 300,250 H 450 V 750 H 300 Z m 250,0 H 700 V 750 H 550 Z" /><path
-   style="display:inline;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:3;stroke-dasharray:none;stroke-opacity:1"
+<rect
+   style="vector-effect:non-scaling-stroke;fill:url(#radialGradient4);fill-opacity:1;stroke:none;stroke-opacity:1;-inkscape-stroke:hairline"
+   id="rect3"
+   width="1000"
+   height="1000"
+   x="0"
+   y="0" /><path
+   style="display:inline;fill:#121212;fill-opacity:1;stroke:none;stroke-width:3;stroke-dasharray:none;stroke-opacity:1"
    id="path10"
-   d="M 800,500 574.99999,629.90381 350,759.80762 l 0,-259.80763 0,-259.80761 225.00001,129.90381 z"
-   transform="translate(-50)" /></svg>
+   d="M 682.5,500 524.99999,590.93267 367.5,681.86533 V 499.99999 318.13467 l 157.50001,90.93266 z" /></svg>
index e6dd88535e5b899a0275969fbc2c144dcf769999..e91da14a1ab627c5c34d0fd5ddd2804bd3e0e401 100644 (file)
@@ -1,7 +1,6 @@
 <html>
        <head>
                <style>
-
 body {
        position: absolute;
        top: 0;
@@ -10,56 +9,98 @@ body {
        right: 0;
        margin: 0;
        overflow: hidden;
-       color: var(--background)
+       border: 1px solid var(--primary);
+       color: var(--background);
 }
 img {
-       height: 100vh;
+       height: calc(100vh - 2px);
 }
 audio {
        margin: 4px;
        width: calc(100% - 8px);
        height: 20px;
 }
+
 #playerMain {
        display: inline-block;
        vertical-align: top;
-       width: calc((100vw - 100vh) * 0.5);
-       height: 100vh;
-
-       background-color: var(--primary);
+       width: calc(100vw - 120vh - 1px);
+       height: calc(100vh - 2px);
+}
+#canvas {
+       position: absolute;
+       top: 0;
+       left: calc(100vh - 2px);
+       height: calc(100vh - 2px);
+       width: calc(100vw - 120vh + 1px);
+       z-index: -1;
+       opacity: 0;
+       transition: opacity 1s;
+}
+.showingCanvas {
+       opacity: 1 !important;
 }
 #playerInfo {
+       position: absolute;
+       top: 0;
+       left: calc(100vw - 20vh);
+       width: calc(100vw - 100vh);
+       height: calc(100vh - 2px);
+       background: var(--background);
+       transition: left 0.7s cubic-bezier(.46,.03,.52,.96);
+}
+.showingInfo {
+       left: calc(100vh - 2px) !important;
+}
+#infoButton {
+       display: inline-block;
+       vertical-align: top;
+       height: 100%;
+       width: 20vh;
+       background-color: var(--off-primary);
+       border: none;
+}
+#playerInfoBox {
        display: inline-block;
        vertical-align: top;
-       width: calc(((100vw - 100vh) * 0.5) - 9px);
-       height: 100vh;
        overflow: scroll;
-       padding: 4px;
-
-       background-color: var(--secondary);
+       height: 100%;
+       width: calc(100vw - 120vh - 12px);
+       margin: 5px;
+       color: var(--primary);
 }
-#stationName {
+#playerInfoText {
+       margin-top: 0;
+       opacity: 0;
+       transition: opacity 0.5s;
+}
+.showingInfo > #playerInfoBox > #playerInfoText {
+       opacity: 1 !important;
+}
+#overlayBar {
        position: absolute;
-       bottom: 0;
-       left: 100vh;
-       margin: 0;
-       color: var(--off-primary);
-       font-size: 2em;
-       line-height: 1em;
+       top: -1px;
+       right: -1px;
+       width: 1px;
+       height: 100vh;
+       background-color: var(--primary);
 }
+
 #playerPlaying {
        width: calc(100% - 16px);
        margin: 4px;
        padding: 4px;
+
        color: var(--primary);
-       background-color: var(--dark);
+       background-color: var(--transparent-dark);
 }
+
 #pauseIcon, #playIcon {
        position: absolute;
        top: 0;
        left: 0;
-       width: 100vh;
-       height: 100vh;
+       width: calc(100vh - 2px);
+       height: calc(100vh - 2px);
 }
 #allIcon {
        opacity: 0;
@@ -69,15 +110,6 @@ audio {
        opacity: 1;
 }
 
-@media only screen and (max-width : 700px) {
-       #playerMain {
-               width: calc((100vw - 100vh) - 1px);
-       }
-       #playerInfo {
-               display: none;
-       }
-}
-
 /* Remove default apperance */
 input[type="range"] {
        margin: 4px;
@@ -91,7 +123,6 @@ input[type="range"] {
   /*  overflow: hidden;  remove this line*/
   background: var(--background);
 }
-
 /* Thumb: webkit */
 input[type="range"]::-webkit-slider-thumb {
   -webkit-appearance: none;
@@ -103,7 +134,6 @@ input[type="range"]::-webkit-slider-thumb {
   border: none;
   transition: .2s ease-in-out;
 }
-
 /* Thumb: Firefox */
 input[type="range"]::-moz-range-thumb {
   height: 10px;
@@ -141,18 +171,71 @@ input[type="range"]:focus::-moz-range-thumb {
                <link rel="stylesheet" href="/static/style.css">
                <script>
 
+window.AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext;
+
 const player = new Audio("https://stream.ozva.co.uk:8443/critters");
+player.crossOrigin = "anonymous";
+
+// setup variables
+var canvas = "";
+var ctx = ""
+var analyser = "";
+
 var playing = false;
 
+function getAudio() {
+       let audioContext = new AudioContext();
+       let audioSource = audioContext.createMediaElementSource(player);
+
+       // setup analyser
+       analyser = audioContext.createAnalyser();
+       audioSource.connect(analyser);
+       analyser.connect(audioContext.destination);
+       analyser.fftSize = 512;
+
+       canvas = document.getElementById('canvas');
+       dimentions = document.getElementById("canvas").getBoundingClientRect();
+       canvas.width = dimentions.width;
+       canvas.height = dimentions.height;
+       canvas.classList.add("showingCanvas");
+
+       ctx = canvas.getContext('2d');
+}
+
+function renderFrame() {
+       let points = 128;
+
+       var array = new Uint8Array(analyser.frequencyBinCount);
+       analyser.getByteFrequencyData(array);
+
+       var dataStep = Math.round((array.length / 2) / points); //sample limited data from the total array
+       var pixelStep = Math.round(canvas.width / points); //sample limited data from the total array
+
+       ctx.clearRect(0, 0, canvas.width, canvas.height);
+       ctx.beginPath();
+       ctx.moveTo(0, canvas.height - (array[0] * (canvas.height / 255) * 0.75));
+
+       for (var i = 0; i < points; i++) {
+               var value = array[i * dataStep];
+               ctx.lineTo(pixelStep * i, canvas.height - (value * (canvas.height / 255) * 0.75) + 2);
+       }
+
+       ctx.strokeStyle = "rgb( 43 85 54 )";
+       ctx.lineWidth = 2;
+       ctx.stroke();
+
+       requestAnimationFrame(renderFrame);
+       }
+
 function getInfo () {
     fetch("/api/0")
     .then(data => data.text())
     .then(data => JSON.parse(data))
     .then(data => {
         document.getElementById("playerCover").src = data.cover_path;
-        document.getElementById("playerInfo").innerHTML = data.info;
+        document.getElementById("playerInfoText").innerHTML = data.info;
         document.getElementById("playerPlaying").innerHTML = `
-        <em>Now playing:</em> <a href="${data.link}">${data.title}</a> - ${data.artist} <em>(${data.year})</em>
+        <em>Now playing:</em> <a href="${data.link}" target="_blank">${data.title}</a> - ${data.artist} <em>(${data.year})</em>
         `;
     })
 }
@@ -169,6 +252,8 @@ function toggleAudio () {
                document.getElementById("playIcon").style = "";
                document.getElementById("pauseIcon").style = "display: none;";
        } else {
+               if (!ctx) {getAudio();}
+               renderFrame();
                player.play();
                playing = true;
                document.getElementById("playIcon").style = "display: none;";
@@ -176,23 +261,30 @@ function toggleAudio () {
        }
 }
 
+function toggleInfo() {
+       document.getElementById("playerInfo").classList.toggle("showingInfo");
+       console.log("done");
+}
+
 setInterval(setVolume, 100);
 setInterval(getInfo, 4000);
                </script>
        </head>
        <body onload="getInfo();document.getElementById('volumeControl').style = '';">
                <img id="playerCover" src="/api/cover/0" /><div id="playerMain">
+                       <canvas id="canvas" class=""></canvas>
                        <input id="volumeControl" style="display: none;" type="range" min="0" max="1" step="0.01"/>
                        <noscript>
-                               <audio src="https://stream.ozva.co.uk:8443/critters" controls></audio><br>
+                               <audio id="audio" src="https://stream.ozva.co.uk:8443/critters" controls></audio><br>
                        </noscript>
                        <p id="playerPlaying">Currently playing track info available with the JS player</p>
-               </div><div id="playerInfo">
+               </div><div id="playerInfo" class="">
+                       <input type="button" value="&#9432;" id="infoButton" onclick="toggleInfo();" /><div id="playerInfoBox"><p id="playerInfoText"></p></div>
                </div>
-               <h1 id="stationName"><em>Tree Critters Radio</em></h1>
                <div id="allIcon">
                        <img onclick="toggleAudio();" id="playIcon" style="" src="/static/play.svg" />
                        <img onclick="toggleAudio();" id="pauseIcon" style="display: none;" src="/static/pause.svg" />
                </div>
+               <div id="overlayBar"></div>
        </body>
 </html>
index 55cfd7534ecaec67ffde1a726de8c8c6a3140cc8..2832c27303cdb2fb29ed27a0b59236d136f18fc1 100644 (file)
@@ -1,6 +1,7 @@
 :root {
     --background: #111111;
     --dark: #151515;
+    --transparent-dark: rgba(21, 21, 21, 0.75);
     --primary: #70b783;
     --off-primary: #4d9961;
     --secondary: #c6ce73;
index b98a98df834ceaff9bde94a872d8bac5b65c44fc..2660fbef589233d01e0e40fd9d1101e14d4c66a8 100644 (file)
@@ -10,6 +10,7 @@
                <iframe style="border: none; width: 600px; height: 100px;" src="/static/player.html"></iframe><br>
                <h2>Player widget with track information:</h2>
                <iframe style="border: none; width: 800px; height: 100px;" src="/static/player.html"></iframe><br>
+               <iframe style="border: none; width: 800px; height: 100px;" src="/static/pallet.html"></iframe><br>
                <h2>Notes:</h2>
                <p>
                        Plently to do on the delivery front!
@@ -18,9 +19,8 @@
                        <li>Need a better font</li>
                        <li>Need a better design for the player
                                <ul>
-                                       <li>Redesign of the play pause buttons</li>
-                                       <li>Better color pallet / color choices (+ integration of lightmode?)</li>
-                                       <li>Better display of additional information? (+ possibly a togglable overlay?)</li>
+                                       <li>Redesign of the play pause buttons again?</li>
+                                       <li>Integration of lightmode?)</li>
                                </ul>
                        </li>
                        <li>Integration with different types of audio for the station