Changeset - 8d87a3528369
[Not reviewed]
default
0 4 1
drewp@bigasterisk.com - 13 years ago 2012-06-18 01:13:18
drewp@bigasterisk.com
go button support
Ignore-this: e32b66cb39bf05a2fec5c91fdb7a7093
5 files changed with 48 insertions and 27 deletions:
0 comments (0 inline, 0 general)
bin/ascoltami2
Show inline comments
 
#!bin/python
 
import web, thread, gobject, sys, optparse, logging
 
from rdflib import URIRef
 
sys.path.append(".")
 
from light9.ascoltami.player import Player
 
from light9.ascoltami.playlist import Playlist, NoSuchSong
 
from light9.ascoltami.webapp import makeWebApp
 
from light9.ascoltami.webapp import makeWebApp, songUri, songLocation
 
from light9 import networking, showconfig
 

	
 

	
 
import BaseHTTPServer
 
BaseHTTPServer.BaseHTTPRequestHandler.log_message = \
 
                     lambda self, format, *args: None
 
@@ -30,20 +30,20 @@ class App:
 
        mainloop.run()
 

	
 
    def onEOS(self, song):
 
        self.player.pause()
 
        self.player.seek(0)
 

	
 
        # stop here for now- no go-button behavior
 
        return
 
        thisSongUri = songUri(graph, URIRef(song))
 

	
 
        try:
 
            nextSong = self.playlist.nextSong(song)
 
            nextSong = self.playlist.nextSong(thisSongUri)
 
        except NoSuchSong: # we're at the end of the playlist
 
            return
 

	
 
        self.player.setSong(nextSong, play=False)
 
        self.player.setSong(songLocation(graph, nextSong), play=False)
 

	
 
if __name__ == "__main__":
 
    logging.basicConfig()
 
    log = logging.getLogger()
 
    gobject.threads_init()
 

	
bin/gobutton
Show inline comments
 
new file 100644
 
#!/bin/sh
 
# uri should be set from $LIGHT9_SHOW/config.n3
 
exec curl --silent -d '' http://localhost:8040/go
light9/ascoltami/index.html
Show inline comments
 
@@ -116,13 +116,13 @@
 
	$.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 () {
 
	// todo
 
	$.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({
 
@@ -156,7 +156,7 @@
 
});
 
// ]]>
 
</script>
 

	
 

	
 
  </body>
 
</html>
 
\ No newline at end of file
 
</html>
light9/ascoltami/player.py
Show inline comments
 
@@ -18,12 +18,13 @@ class Player(object):
 
        just finished."""
 
        self.autoStopOffset = autoStopOffset
 
        self.playbin = self.pipeline = gst.parse_launch("playbin2")
 
        self.playStartTime = 0
 
        self.lastWatchTime = 0
 
        self.autoStopTime = 0
 
        self.lastSetSongUri = None
 
        self.onEOS = onEOS
 
        
 
        # 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)
 
@@ -54,20 +55,12 @@ class Player(object):
 
            log.debug("watch %s < %s < %s",
 
                      self.lastWatchTime, self.autoStopTime, t)
 
            if self.lastWatchTime < self.autoStopTime < t:
 
                log.info("autostop")
 
                self.pause()
 

	
 
                # new EOS logic above should be better
 
            ## if not self.onEOS:
 
            ##     if self.isPlaying() and t >= self.duration() - .2:
 
            ##         # i don't expect to hit dur exactly with this
 
            ##         # polling. What would be better would be to watch for
 
            ##         # the EOS signal and react to that
 
            ##         self.onEOS(self.getSong())
 

	
 
            self.lastWatchTime = t
 
        except:
 
            traceback.print_exc()
 
        return True
 

	
 
    def seek(self, t):
 
@@ -82,20 +75,22 @@ class Player(object):
 
        uri like file:///my/proj/light9/show/dance2010/music/07.wav
 
        """
 
        log.info("set song to %r" % songLoc)
 
        self.pipeline.set_state(gst.STATE_READY)
 
        self.preload(songLoc)
 
        self.pipeline.set_property("uri", songLoc)
 
        self.lastSetSongUri = songLoc
 
        # todo: don't have any error report yet if the uri can't be read
 
        if play:
 
            self.pipeline.set_state(gst.STATE_PLAYING)
 
            self.playStartTime = time.time()
 

	
 
    def getSong(self):
 
        """Returns the URI of the current song."""
 
        return self.playbin.get_property("uri")
 
        # even the 'uri' that I just set isn't readable yet
 
        return self.playbin.get_property("uri") or self.lastSetSongUri
 

	
 
    def preload(self, songPath):
 
        """
 
        to avoid disk seek stutters, which happened sometimes (in 2007) with the
 
        non-gst version of this program, we read the whole file to get
 
        more OS caching.
 
@@ -126,18 +121,22 @@ class Player(object):
 
        return {"current": {"name":state.value_nick},
 
                "pending": {"name":state.value_nick}}
 
        
 
    def pause(self):
 
        self.pipeline.set_state(gst.STATE_PAUSED)
 

	
 
    def isAutostopped(self):
 
        """
 
        are we stopped at the autostop time?
 
        """
 
        pos = self.currentTime()
 
        autoStop = self.duration() - self.autoStopOffset
 
        return not self.isPlaying() and abs(pos - autoStop) < 1 # i've seen .4 difference here
 

	
 
    def resume(self):
 
        self.pipeline.set_state(gst.STATE_PLAYING)
 
        pos = self.currentTime()
 
        autoStop = self.duration() - self.autoStopOffset
 
        if abs(pos - autoStop) < .01:
 
            self.releaseAutostop()
 

	
 
    def setupAutostop(self):
 
        dur = self.duration()
 
        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
light9/ascoltami/webapp.py
Show inline comments
 
@@ -21,25 +21,28 @@ class root(object):
 
    def GET(self):
 
        web.header("Content-type", "application/xhtml+xml")
 
        # todo: use a template; embed the show name and the intro/post
 
        # times into the page
 
        return render.index(host=socket.gethostname())
 

	
 
def playerSongUri(graph, player):
 
    """or None"""
 
    
 
    playingLocation = player.getSong()
 
    if playingLocation:
 
        return songUri(graph, URIRef(playingLocation))
 
    else:
 
        return None
 

	
 
class timeResource(object):
 
    def GET(self):
 
        player = app.player
 
        graph = app.graph
 

	
 
        playingLocation = player.getSong()
 
        if playingLocation:
 
            song = songUri(graph, URIRef(playingLocation))
 
        else:
 
            song = None
 
        web.header("content-type", "application/json")
 
        return json.dumps({
 
            "song" : song,
 
            "song" : playerSongUri(graph, player),
 
            "started" : player.playStartTime,
 
            "duration" : player.duration(),
 
            "playing" : player.isPlaying(),
 
            "t" : player.currentTime(),
 
            "state" : player.states(),
 
            })
 
@@ -95,19 +98,35 @@ class seekPlayOrPause(object):
 

	
 
class output(object):
 
    def POST(self):
 
        d = json.loads(web.data())
 
        subprocess.check_call(["bin/movesinks", str(d['sink'])])
 

	
 
class goButton(object):
 
    def POST(self):
 
        """
 
        if music is playing, this silently does nothing.
 
        """
 
        graph, player = app.graph, app.player
 

	
 
        if player.isPlaying():
 
            pass
 
        else:
 
            player.resume()
 
            
 
        web.header("content-type", "text/plain")
 
        return "ok"
 

	
 
def makeWebApp(theApp):
 
    global app
 
    app = theApp
 

	
 
    urls = (r"/", "root",
 
            r"/time", "timeResource",
 
            r"/song", "songResource",
 
            r"/songs", "songs",
 
            r"/seekPlayOrPause", "seekPlayOrPause",
 
            r"/output", "output",
 
            r"/go", "goButton",
 
            )
 

	
 
    return web.application(urls, globals(), autoreload=False)
0 comments (0 inline, 0 general)