Changeset - b7a3dff5514d
[Not reviewed]
default
0 3 0
drewp@bigasterisk.com - 3 years ago 2022-05-13 08:09:14
drewp@bigasterisk.com
rough and untested port of asco from jquery to vanilla
3 files changed with 168 insertions and 170 deletions:
0 comments (0 inline, 0 general)
light9/ascoltami/index.html
Show inline comments
 
@@ -3,10 +3,7 @@
 
  <head>
 
    <title>ascoltami on {{host}}</title>
 
    
 
    <script type="text/javascript" src="/lib/jquery/dist/jquery.min.js"></script>
 
    <script type="text/javascript" src="/lib/jquery-ui/jquery-ui.min.js"></script>
 
    <link rel="Stylesheet" type="text/css" href="/lib/jquery-ui/themes/smoothness/jquery-ui.min.css"/>
 
    <link rel="Stylesheet" type="text/css" href="style.css"/>
 
    <link rel="Stylesheet" type="text/css" href="style.css">
 
    <style>
 
        #cmd-go { min-width: 5em; }
 
        .song-name { padding-left: 0.4em; }
 
@@ -55,7 +52,5 @@
 
    <p><a href="">reload</a></p>
 
    
 
    <script type="module" src="main.ts"></script>
 

	
 

	
 
  </body>
 
</html>
light9/ascoltami/main.py
Show inline comments
 
#!bin/python
 
import logging
 
import optparse
 
import sys
 
from typing import cast
 

	
 
import gi
 
from light9.run_local import log
 
from rdflib import URIRef
 
from twisted.internet import reactor
 
import sys, optparse, logging
 
from rdflib import URIRef
 
import gi
 
from twisted.internet.interfaces import IReactorCore
 

	
 
gi.require_version('Gst', '1.0')
 
gi.require_version('Gtk', '3.0')
 

	
 
from gi.repository import GObject, Gst
 
from light9 import networking, showconfig
 
from light9.ascoltami.player import Player
 
from light9.ascoltami.playlist import Playlist, NoSuchSong
 
from light9.ascoltami.webapp import makeWebApp, songUri, songLocation
 
from light9 import networking, showconfig
 
from light9.ascoltami.playlist import NoSuchSong, Playlist
 
from light9.ascoltami.webapp import makeWebApp, songLocation, songUri
 

	
 
from gi.repository import GObject, Gst
 
reactor = cast(IReactorCore, reactor)
 

	
 

	
 
class App(object):
 
@@ -41,17 +48,9 @@ if __name__ == "__main__":
 
    Gst.init(None)
 

	
 
    parser = optparse.OptionParser()
 
    parser.add_option(
 
        '--show',
 
        help='show URI, like http://light9.bigasterisk.com/show/dance2008',
 
        default=showconfig.showUri())
 
    parser.add_option("-v",
 
                      "--verbose",
 
                      action="store_true",
 
                      help="logging.DEBUG")
 
    parser.add_option("--twistedlog",
 
                      action="store_true",
 
                      help="twisted logging")
 
    parser.add_option('--show', help='show URI, like http://light9.bigasterisk.com/show/dance2008', default=showconfig.showUri())
 
    parser.add_option("-v", "--verbose", action="store_true", help="logging.DEBUG")
 
    parser.add_option("--twistedlog", action="store_true", help="twisted logging")
 
    (options, args) = parser.parse_args()
 

	
 
    log.setLevel(logging.DEBUG if options.verbose else logging.INFO)
light9/ascoltami/main.ts
Show inline comments
 
function byId(id: string): HTMLElement {
 
  return document.getElementById(id)!;
 
}
 

	
 
async function onLoad() {
 
const config = await (await fetch('config')).json();
 
const times = config.times;
 
document.title = document.title.replace('{{host}}', config.host);
 
const h1 =document.querySelector('h1')!
 
h1.innerText = h1?.innerText.replace('{{host}}', config.host)
 
/*
 
    $("#nav").text(navigator.userAgent);
 
    var updateFreq = (navigator.userAgent.indexOf("Linux") != -1) ? 10 : 2;
 
    if (navigator.userAgent.match(/Windows NT/)) {
 
      // helper laptop
 
      updateFreq = 10;
 
    }
 
    $("#updateReq").text(updateFreq);
 
  const config = await (await fetch("api/config")).json();
 
  const times = config.times;
 
  document.title = document.title.replace("{{host}}", config.host);
 
  const h1 = document.querySelector("h1")!;
 
  h1.innerText = h1.innerText.replace("{{host}}", config.host);
 

	
 
    var times = {% raw times %};
 
  byId("nav").innerText = navigator.userAgent;
 
  var updateFreq = navigator.userAgent.indexOf("Linux") != -1 ? 10 : 2;
 
  if (navigator.userAgent.match(/Windows NT/)) {
 
    // helper laptop
 
    updateFreq = 10;
 
  }
 
  byId("updateReq").innerText = "" + updateFreq;
 

	
 
  let currentDuration = 0;
 
  let currentHighlightedSong = "";
 
  let lastPlaying = false;
 

	
 
    var currentDuration = 0;
 
    var currentHighlightedSong = "";
 
    var lastPlaying;
 
    function updateCurrent(doneCallback) {
 
	$.getJSON("time", {}, function (data, status) {
 
	    $("#currentSong").text(data.song);
 
	    if (data.song != currentHighlightedSong) {
 
		showCurrentSong(data.song);
 
	    }
 
	    $("#currentTime").text(data.t.toFixed(1));
 
	    $("#leftTime").text((data.duration - data.t).toFixed(1));
 
	    $("#leftAutoStopTime").text(
 
		Math.max(0, data.duration - times.post - data.t).toFixed(1));
 
	    $("#states").text(JSON.stringify(data.state));
 
	    currentDuration = data.duration;
 
	    $("#timeSlider").slider({value: data.t,
 
				     max: data.duration});
 
	    if (data.playing != lastPlaying) {
 
		$(".playMode").removeClass("active");
 
		$(data.playing ? "#cmd-play" : "#cmd-stop").addClass("active");
 
		lastPlaying = data.playing;
 
	    }
 
            $("#next").text(data.next);
 
	    doneCallback();
 
	});
 
  async function updateCurrent() {
 
    const data = await (await fetch("api/time")).json();
 
    byId("currentSong").innerText = data.song;
 
    if (data.song != currentHighlightedSong) {
 
      showCurrentSong(data.song);
 
    }
 
    byId("currentTime").innerText = data.t.toFixed(1);
 
    byId("leftTime").innerText = (data.duration - data.t).toFixed(1);
 
    byId("leftAutoStopTime").innerText = Math.max(0, data.duration - times.post - data.t).toFixed(1);
 
    byId("states").innerText = JSON.stringify(data.state);
 
    currentDuration = data.duration;
 
    //   document.querySelector("#timeSlider").slider({ value: data.t, max: data.duration });
 
    if (data.playing != lastPlaying) {
 
      document.querySelectorAll(".playMode").forEach((e: Element) => e.classList.remove("active"));
 
      byId(data.playing ? "cmd-play" : "cmd-stop").classList.add("active");
 
      lastPlaying = data.playing;
 
    }
 
    function showCurrentSong(uri) {
 
	$(".songs div").each(function (i, row) {
 
	    row = $(row);
 
	    if (row.find("button").data("uri") == uri) {
 
		row.addClass("currentSong");
 
	    } else {
 
		row.removeClass("currentSong");
 
	    }
 
	});
 
	currentHighlightedSong = uri;
 
    }
 
    $.getJSON("songs", {}, function (data, status) {
 
	$.each(data.songs, function (i, song) {
 
	    var button = $("<button>");
 
            // link is just for dragging, not clicking
 
            var link = $("<a>");
 
            link.append($("<span>").addClass("num").text(song.label.slice(0,2)));
 
            link.append($("<span>").addClass("song-name").text(song.label.slice(2).trim()));
 
            link.attr("href", song.uri);
 
            link.click(function () { button.click(); return false; }); 
 
            button.append(link);
 
	    button.data(song);
 
	    button.click(function () {
 
		$.post("song", button.data("uri"), 
 
		       function (data, textStatus, xhr) {
 
			   showCurrentSong(song.uri);
 
		       });
 
	    });
 
	    $(".songs").append($("<div>").append(button));
 
	});
 
    byId("next").innerText = data.next;
 
  }
 

	
 
  function showCurrentSong(uri: string) {
 
    document.querySelectorAll(".songs div").forEach((row: Element, i: number) => {
 
      if (row.querySelector("button")!.dataset.uri == uri) {
 
        row.classList.add("currentSong");
 
      } else {
 
        row.classList.remove("currentSong");
 
      }
 
    });
 
    currentHighlightedSong = uri;
 
  }
 

	
 
  	const data = await (await fetch('api/songs')).json()
 
      data.songs.forEach((song)=> {
 
        const button = document.createElement("button");
 
        // link is just for dragging, not clicking
 
        const link = document.createElement("a");
 
        link.appendChild($("<span>").addClass("num").text(song.label.slice(0, 2)));
 
        link.appendChild($("<span>").addClass("song-name").text(song.label.slice(2).trim()));
 
        link.setAttribute("href", song.uri);
 
        link.addEventListener("click", (ev) => {
 
			ev.stopPropagation()
 
          button.click();
 
        });
 
        button.appendChild(link);
 
        button.dataset.uri=(song);
 
        button.click(function () {
 
          fetch('api/song', {method: 'POST', body: song$.post("song", button.data("uri"), function (data, textStatus, xhr) {
 
            showCurrentSong(song.uri);
 
          });
 
        });
 
        $(".songs").append($("<div>").append(button));
 
      });
 
    });
 

	
 
    var tojs = JSON.stringify;
 

	
 
    $(document).keypress(function (ev) {
 

	
 
	if (ev.which == 115) { $("#cmd-stop").click(); return false; }
 
	if (ev.which == 112) { $("#cmd-play").click(); return false; }
 
	if (ev.which == 105) { $("#cmd-intro").click(); return false; }
 
	if (ev.which == 116) { $("#cmd-post").click(); return false; }
 

	
 
	if (ev.key == 'g') {
 
            $("#cmd-go").click();
 
            return false;
 
        }
 
	return true;
 
    });
 

	
 
    $("#cmd-stop").click(function () { $.post("time", tojs({pause: true})); });
 
    $("#cmd-play").click(function () { $.post("time", tojs({resume: true})); });
 
    $("#cmd-intro").click(function () { 
 
	$.post("time", tojs({t: times.intro, resume: true}))
 
    });
 
    $("#cmd-post").click(function () { 
 
	$.post("time", tojs({t: currentDuration - times.post, resume: true}))
 
    });
 
    $("#cmd-go").click(function () {
 
	$.post("go");
 
    });
 
    $("#cmd-out0").click(function () { $.post("output", tojs({sink: "0"})); })
 
    $("#cmd-out1").click(function () { $.post("output", tojs({sink: "1"})); })
 

	
 
    var pendingSlide = false;
 
    $("#timeSlider").slider({
 
	step: .01,
 
	slide: function (event, ui) {
 
	    if (pendingSlide) {
 
		return;
 
	    }
 
	    pendingSlide = true;
 
	    $.post("time", '{"t" : '+ui.value+'}', 
 
		   function (data, status, xhr) {
 
		       pendingSlide = false;
 
		   });
 
	},
 
    });
 
    
 
    var raf = window.requestAnimationFrame ||
 
	window.mozRequestAnimationFrame || 
 
	window.webkitRequestAnimationFrame;
 

	
 
    var recentUpdates = [];
 
    function onUpdate() {
 
        recentUpdates.push(+new Date());
 
        recentUpdates = recentUpdates.slice(Math.max(recentUpdates.length - 5, 0));
 
        refreshUpdateFreqs();
 
  document.addEventListener("keypress", (ev) => {
 
    if (ev.which == 115) {
 
      byId("cmd-stop").click();
 
      return false;
 
    }
 
    if (ev.which == 112) {
 
      byId("cmd-play").click();
 
      return false;
 
    }
 
    if (ev.which == 105) {
 
      byId("cmd-intro").click();
 
      return false;
 
    }
 
    if (ev.which == 116) {
 
      byId("cmd-post").click();
 
      return false;
 
    }
 

	
 
    function refreshUpdateFreqs() {
 
        if (recentUpdates.length > 1) {
 
          if (+new Date() - recentUpdates[recentUpdates.length - 1] > 1000) {
 
            $("#updateActual").text("(stalled)");
 
            $(".dimStalled").addClass("stalled");
 
            return;
 
          }
 
    if (ev.key == "g") {
 
      byId("cmd-go").click();
 
      return false;
 
    }
 
    return true;
 
  });
 

	
 
  async function postJson(url: string, jsBody: Object) {
 
    return fetch(url, { method: "POST", headers: { "Content-Type": "applcation/json" }, body: JSON.stringify(jsBody) });
 
  }
 

	
 
          var avgMs = (recentUpdates[recentUpdates.length - 1] - recentUpdates[0]) / (recentUpdates.length - 1);
 
          $("#updateActual").text(Math.round(1000 / avgMs));
 
        }
 
    }
 
    setInterval(refreshUpdateFreqs, 2000);
 
  byId("cmd-stop").addEventListener("click", (ev: Event) => postJson("time", { pause: true }));
 
  byId("cmd-play").addEventListener("click", (ev: Event) => postJson("time", { resume: true }));
 
  byId("cmd-intro").addEventListener("click", (ev: Event) => postJson("time", { t: times.intro, resume: true }));
 
  byId("cmd-post").addEventListener("click", (ev: Event) => postJson("time", { t: currentDuration - times.post, resume: true }));
 
  byId("cmd-go").addEventListener("click", (ev: Event) => postJson("go", {}));
 
  byId("cmd-out0").addEventListener("click", (ev: Event) => postJson("output", { sink: "0" }));
 
  byId("cmd-out1").addEventListener("click", (ev: Event) => postJson("output", { sink: "1" }));
 

	
 
  //   var pendingSlide = false;
 
  //   $("#timeSlider").slider({
 
  //     step: 0.01,
 
  //     slide: function (event, ui) {
 
  //       if (pendingSlide) {
 
  //         return;
 
  //       }
 
  //       pendingSlide = true;
 
  //       $.post("time", '{"t" : ' + ui.value + "}", function (data, status, xhr) {
 
  //         pendingSlide = false;
 
  //       });
 
  //     },
 
  //   });
 

	
 
    function updateLoop() {
 
	var whenDone = function () {
 
	    setTimeout(function () { 
 
		raf(updateLoop);
 
	    }, 1000 / updateFreq);
 
	};
 
        onUpdate();
 
	updateCurrent(whenDone);
 
  let recentUpdates: Array<number> = [];
 
  function onUpdate() {
 
    recentUpdates.push(+new Date());
 
    recentUpdates = recentUpdates.slice(Math.max(recentUpdates.length - 5, 0));
 
    refreshUpdateFreqs();
 
  }
 

	
 
  function refreshUpdateFreqs() {
 
    if (recentUpdates.length > 1) {
 
      if (+new Date() - recentUpdates[recentUpdates.length - 1] > 1000) {
 
        byId("updateActual").innerText = "(stalled)";
 
        document.querySelectorAll(".dimStalled").forEach((el) => el.classList.add("stalled"));
 
        return;
 
      }
 

	
 
      var avgMs = (recentUpdates[recentUpdates.length - 1] - recentUpdates[0]) / (recentUpdates.length - 1);
 
      byId("updateActual").innerText = "" + Math.round(1000 / avgMs);
 
    }
 
    updateLoop();
 
*/
 
  }
 
  setInterval(refreshUpdateFreqs, 2000);
 

	
 
  async function updateLoop() {
 
    var whenDone = function () {
 
      setTimeout(function () {
 
        requestAnimationFrame(updateLoop);
 
      }, 1000 / updateFreq);
 
    };
 
    onUpdate();
 
    await updateCurrent();
 
	whenDone();
 
  }
 
  updateLoop();
 
}
 
onLoad()
 
\ No newline at end of file
 
onLoad();
0 comments (0 inline, 0 general)