Files @ 1cb63991eb19
Branch filter:

Location: light9/light9/ascoltami/index.html

Drew Perttula
asco use cyclone templating instead of genshi
Ignore-this: 1f66e01d6e3a11c5abad8f594027f514
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" 
      xmlns:py="http://genshi.edgewall.org/">
  <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"/>
    <style>
        #cmd-go { min-width: 5em; }
        .song-name { padding-left: 0.4em; }
    </style>
  </head>
  <body>
    <h1>ascoltami on {{host}}</h1>
    <div class="songs"/>

    <div class="dimStalled">
      <table>
        <tr><td colspan="3"><strong>Song:</strong> <span id="currentSong"/></td></tr>
        <tr>
          <td><strong>Time:</strong> <span id="currentTime"/></td>
          <td><strong>Left:</strong> <span id="leftTime"/></td>
          <td><strong>Until autostop:</strong> <span id="leftAutoStopTime"/></td>
        </tr>
        <tr>

          <td colspan="3">
            <strong>Update freq:</strong> requested <span id="updateReq"/>, actual <span id="updateActual"/>
            <strong>States:</strong> <span id="states"/>
          </td>
          
        </tr>
      </table>
      
      <div class="timeRow">
        <div id="timeSlider"/>
      </div>
    </div>
    <div class="commands">
      <button id="cmd-stop" class="playMode"><strong>Stop</strong><div class="key">s</div></button>
      <button id="cmd-play" class="playMode"><strong>Play</strong> <div class="key">p</div></button>
      <button id="cmd-intro"><strong>Skip intro</strong> <div class="key">i</div></button>
      <button id="cmd-post"><strong>Skip to Post</strong> <div class="key">t</div></button>
      <button id="cmd-go"><strong>Go</strong> <div class="key">g</div><div id="next"></div></button>

      <!--
      <button id="cmd-out0"><strong>Output 0</strong></button>
      <button id="cmd-out1"><strong>Output 1</strong></button>
      -->
    </div>
    
    <p>Running on <span id="nav"/></p>
    <p><a href="">reload</a></p>

<script type="text/javascript">
// <![CDATA[
$(function () {

    $("#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);

    var times = {% raw times %};

    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();
	});
    }
    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));
	});
    });

    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();
    }

    function refreshUpdateFreqs() {
        if (recentUpdates.length > 1) {
          if (+new Date() - recentUpdates[recentUpdates.length - 1] > 1000) {
            $("#updateActual").text("(stalled)");
            $(".dimStalled").addClass("stalled");
            return;
          }

          var avgMs = (recentUpdates[recentUpdates.length - 1] - recentUpdates[0]) / (recentUpdates.length - 1);
          $("#updateActual").text(Math.round(1000 / avgMs));
        }
    }
    setInterval(refreshUpdateFreqs, 2000);

    function updateLoop() {
	var whenDone = function () {
	    setTimeout(function () { 
		raf(updateLoop);
	    }, 1000 / updateFreq);
	};
        onUpdate();
	updateCurrent(whenDone);
    }
    updateLoop();

});
// ]]>
</script>


  </body>
</html>