Changeset - e8f6722a3881
[Not reviewed]
default
0 4 0
drewp@bigasterisk.com - 15 years ago 2010-06-12 07:00:54
drewp@bigasterisk.com
ascoltami2 web one is in good shape. main missing piece is the auto-go button
Ignore-this: 2a43f2b25b7b011437e8011bbab15954
4 files changed with 158 insertions and 73 deletions:
0 comments (0 inline, 0 general)
light9/ascoltami/index.html
Show inline comments
 
@@ -11,50 +11,69 @@
 
  </head>
 
  <body>
 

	
 

	
 
    <div class="songs">
 
    </div>
 

	
 
    <div class="songs"/>
 

	
 
    <div>Song: <span id="currentSong"/></div>
 
    <div>Time: <span id="currentTime"/></div>
 
    <div>Left: <span id="leftTime"/></div>
 
    <div>
 
    <div>Until autostop: <span id="leftAutoStopTime"/></div>
 
    <div class="timeRow">
 
      <div id="timeSlider"/>
 
    </div>
 

	
 
    <div class="commands">
 
      <button id="cmd-stop">Stop C-s</button>
 
      <button id="cmd-play">Play C-p</button>
 
      <button id="cmd-intro">Skip intro C-i</button>
 
      <button id="cmd-post">Skip to Post C-t</button>
 
      <button id="cmd-go">Go  space</button>
 
      <button id="cmd-stop" class="playMode">Stop<div class="key">C-s</div></button>
 
      <button id="cmd-play" class="playMode">Play <div class="key">C-p</div></button>
 
      <button id="cmd-intro">Skip intro <div class="key">C-i</div></button>
 
      <button id="cmd-post">Skip to Post <div class="key">C-t</div></button>
 
      <button id="cmd-go">Go  <div class="key">space</div></button>
 
    </div>
 

	
 
bind keys, spacebar, css work
 
todo: go button actions, display next action
 

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

	
 
    var times = {
 
    var times = { // need to get these from server
 
	intro: 4,
 
	post: 10
 
	post: 4
 
    };
 

	
 
    var currentDuration = 0;
 

	
 
    var currentHighlightedSong = "";
 
    var lastPlaying;
 
    function updateCurrent() {
 
	$.getJSON("time", {}, function (data, status) {
 
	    $("#currentSong").text(data.song);
 
	    $("#currentTime").text(data.t);
 
	    $("#leftTime").text(data.duration - data.t);
 
	    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));
 
	    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;
 
	    }
 
	});
 
    }
 

	
 
    function showCurrentSong(uri) {
 
	$(".songs div").each(function (i, row) {
 
	    row = $(row);
 
	    if (row.find("button").data("path") == uri) {
 
		row.addClass("currentSong");
 
	    } else {
 
		row.removeClass("currentSong");
 
	    }
 
	});
 
	currentHighlightedSong = uri;
 
    }
 
    $.getJSON("songs", {}, function (data, status) {
 
	$.each(data.songs, function (i, song) {
 
	    var button = $("<button>");
 
@@ -63,7 +82,7 @@ bind keys, spacebar, css work
 
	    button.click(function () {
 
		$.post("song", button.data("path"), 
 
		       function (data, textStatus, xhr) {
 
		    
 
			   showCurrentSong(song.uri);
 
		       });
 
	    });
 
	    $(".songs").append($("<div>").append(button));
 
@@ -72,14 +91,27 @@ bind keys, spacebar, css work
 

	
 
    var tojs = JSON.stringify;
 

	
 
    $(document).keypress(function (ev) {
 
	if (1 || ev.ctrlKey) {
 
	    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.which == 32) { $("#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}))});
 
    $("#cmd-intro").click(function () { 
 
	$.post("time", tojs({t: times.intro, resume: true}))
 
    });
 
    $("#cmd-post").click(function () { 
 
	$.post("time", tojs({t: currentDuration - times.post}))
 
	$.post("time", tojs({t: currentDuration - times.post, resume: true}))
 
    });
 
    $("#cmd-go").click(function () {
 
	</i>
 
	// todo
 
    });
 

	
 
    var pendingSlide = false;
 
@@ -95,11 +127,11 @@ bind keys, spacebar, css work
 
		       pendingSlide = false;
 
		   });
 
	},
 
});
 
    });
 
    
 
    function updateLoop() {
 
	updateCurrent();
 
	setTimeout(updateLoop, 300);
 
	setTimeout(updateLoop, 200);
 
    }
 
    updateLoop();
 
});
light9/ascoltami/player.py
Show inline comments
 
@@ -4,38 +4,51 @@
 
alternate to the mpd music player, for ascoltami
 
"""
 
from __future__ import division
 
import time, logging
 
import gst
 
import time, logging, traceback
 
import gst, gobject
 
log = logging.getLogger()
 

	
 
class Player(object):
 
    def __init__(self):
 

	
 
        self.playbin = self.pipeline = gst.parse_launch("playbin2 name=b")
 
    def __init__(self, autoStopOffset=4):
 
        self.autoStopOffset = autoStopOffset
 
        self.playbin = self.pipeline = gst.parse_launch("playbin2")
 
        self.playStartTime = 0
 
        self._duration = 0
 
        self.pauseTime = 0
 
        self.lastWatchTime = 0
 
        self.autoStopTime = 0
 

	
 
        self.setSong("file:///my/proj/light9/show/dance2010/music/07-jacksonmix-complete.wav")
 
        
 
        # before playbin2:
 
        #self.pipeline = gst.parse_launch("filesrc name=file location=%s ! wavparse name=src ! audioconvert ! alsasink name=out" % songFile)
 

	
 
        gobject.timeout_add(50, self.watchTime)
 

	
 
        bus = self.pipeline.get_bus()
 
        bus.add_signal_watch()
 

	
 
        def on_any(bus, msg):
 
            print bus, msg
 

	
 
        bus = self.pipeline.get_bus()
 
        bus.add_signal_watch()
 
        #bus.connect('message', on_any)
 

	
 
        def onStreamStatus(bus, message):
 
            (statusType, _elem) = message.parse_stream_status()
 
            if statusType == gst.STREAM_STATUS_TYPE_ENTER:
 
                self.setupAutostop()
 
        bus.connect('message::stream-status', onStreamStatus)
 

	
 
            # we should run our own poller looking for crosses over the autostop threshold and pausing. When i used the pipeline.seek end-time, it caused lots of unwanted other pausing and was hard to turn off.
 
                
 
            #print message, bus
 
        bus.connect('message::stream-status', onStreamStatus)
 
    def watchTime(self):
 
        try:
 
            try:
 
                t = self.currentTime()
 
            except gst.QueryError:
 
                return True
 
            log.debug("watch %s < %s < %s",
 
                      self.lastWatchTime, self.autoStopTime, t)
 
            if self.lastWatchTime < self.autoStopTime < t:
 
                log.info("autostop")
 
                self.pause()
 
            self.lastWatchTime = t
 
        except:
 
            traceback.print_exc()
 
        return True
 

	
 
    def seek(self, t):
 
        assert self.playbin.seek_simple(
 
@@ -54,17 +67,18 @@ class Player(object):
 
        self.pipeline.set_state(gst.STATE_PLAYING)
 
        self.playStartTime = time.time()
 

	
 

	
 

	
 
#        GST_MESSAGE_DURATION
 
        
 

	
 
    def currentTime(self):
 
        cur, _format = self.playbin.query_position(gst.FORMAT_TIME)
 
        try:
 
            cur, _format = self.playbin.query_position(gst.FORMAT_TIME)
 
        except gst.QueryError:
 
            return 0
 
        return cur / gst.SECOND
 

	
 
    def duration(self):
 
        return self.playbin.query_duration(gst.FORMAT_TIME)[0] / gst.SECOND
 
        try:
 
            return self.playbin.query_duration(gst.FORMAT_TIME)[0] / gst.SECOND
 
        except gst.QueryError:
 
            return 0
 
        
 
    def pause(self):
 
        self.pipeline.set_state(gst.STATE_PAUSED)
 
@@ -72,32 +86,21 @@ class Player(object):
 
    def resume(self):
 
        self.pipeline.set_state(gst.STATE_PLAYING)
 
        pos = self.currentTime()
 
        autoStop = self.duration() - 10
 
        autoStop = self.duration() - self.autoStopOffset
 
        if abs(pos - autoStop) < .01:
 
            self.releaseAutostop()
 

	
 

	
 
    def setupAutostop(self):
 
        return
 
        dur = self.duration()
 
        autoStop = (dur - 10.0)
 
        log.info("autostop will be at %s", autoStop)
 
        print "seek", self.pipeline.seek(1.0, gst.FORMAT_TIME,
 
                           gst.SEEK_FLAG_ACCURATE,
 
                           gst.SEEK_TYPE_NONE, 0,
 
                           gst.SEEK_TYPE_SET, autoStop * gst.SECOND)
 
        self.autoStopTime = (dur - self.autoStopOffset)
 
        log.info("autostop will be at %s", self.autoStopTime)
 
        # pipeline.seek can take a stop time, but using that wasn't
 
        # working out well. I'd get pauses at other times that were
 
        # hard to remove.
 

	
 
    def releaseAutostop(self):
 
        log.info("release autostop")
 
        
 
        print "seek", self.pipeline.seek(
 
            1.0, gst.FORMAT_TIME,
 
            gst.SEEK_FLAG_FLUSH | gst.SEEK_FLAG_ACCURATE | gst.SEEK_FLAG_SKIP,
 
            gst.SEEK_TYPE_NONE, 0,
 
            gst.SEEK_TYPE_END, 0)
 
        print self.pipeline.get_state()
 
        self.pipeline.set_state(gst.STATE_PLAYING)
 

	
 
                           
 
    def isPlaying(self):
 
        _, state, _ = self.pipeline.get_state()
 
        return state == gst.STATE_PLAYING
 
                  
 
                           
 
        
light9/ascoltami/webapp.py
Show inline comments
 
@@ -16,6 +16,7 @@ class timeResource(object):
 
        return jsonlib.write({"song" : player.playbin.get_property("uri"),
 
                              "started" : player.playStartTime,
 
                              "duration" : player.duration(),
 
                              "playing" : player.isPlaying(),
 
                              "t" : player.currentTime()})
 

	
 
    def POST(self):
static/style.css
Show inline comments
 
body { 
 
    background: black;
 
    color: white;
 
    font-family: sans-serif;
 
}
 
.songs {
 
    -moz-column-width:205px;
 
    -webkit-column-width:205px;
 
}
 
.songs button {
 
  display: inline-block;
 
  width: 300px;
 
height: 30px;
 
  text-align: left;
 
    display: inline-block;
 
    width: 200px;
 
    height: 50px;
 
    text-align: left;
 
    background: black;
 
    color: white;
 
    margin: 2px;
 
font-size: 115%;
 
}
 
.songs button:hover {
 
  background: yellow;
 
    color: black;
 
    background: yellow;
 
}
 
body { 
 
    background: black;
 
    color: white;
 
    font-style: sans-serif;
 
}
 
.commands button {
 
    background: black;
 
    color: white;
 
    padding: 20px
 
}
 
.commands button.active {
 
    background: red;
 
}
 

	
 
.songs button:hover {
 
    color: black;
 
    background: yellow;
 
}
 
.commands button {
 
    background: black;
 
    color: white;
 
    padding: 20px
 
}
 
.commands button.active {
 
    background: #1C4054;
 
}
 
.key {
 
    color: #888;
 
}
 
.currentSong button {
 
    background: #55A5C9;
 
}
 
.timeRow {
 
    margin: 14px;
 
}
 
\ No newline at end of file
0 comments (0 inline, 0 general)