changeset 330:1a34a0e118cc

ascoltami: new 'go' button that does the Right Thing during a show
author Drew Perttula <drewp@bigasterisk.com>
date Mon, 19 Jun 2006 00:29:36 +0000
parents b20c8d57aa91
children c579174d73b2
files bin/ascoltami
diffstat 1 files changed, 106 insertions(+), 42 deletions(-) [+]
line wrap: on
line diff
--- a/bin/ascoltami	Sun Jun 18 23:13:43 2006 +0000
+++ b/bin/ascoltami	Mon Jun 19 00:29:36 2006 +0000
@@ -37,6 +37,14 @@
 
 appstyle={'fg':'white','bg':'black'}
 
+def shortSongPath(song, all):
+    prefixlen = len(os.path.commonprefix(all))
+    # include to the last os.sep- dont crop path elements in the middle
+    prefixlen = all[0].rfind(os.sep)+1 
+
+    return os.path.splitext(song[prefixlen:])[0]
+    
+
 class XMLRPCServe(xmlrpc.XMLRPC):
     def __init__(self,player):
         xmlrpc.XMLRPC.__init__(self)
@@ -81,7 +89,7 @@
 
     song_pad_time = 10
     
-    def __init__(self, app, playlist, media=None):
+    def __init__(self):
 
         self.mpd = Mpd()
         reactor.connectTCP(*(networking.mpdServer()+(self.mpd,)))
@@ -197,6 +205,9 @@
             self.mpd.seek(seconds=time, song=1)
         self.last_autopause_time = time
 
+    def in_post(self):
+        return (self.current_time.get() > self.total_time.get() +
+                self.song_pad_time)
 
     def play_pause_toggle(self):
         def finish(status):
@@ -212,13 +223,54 @@
     def skip_to_post(self):
         self.seek_to(self.total_time.get() + self.song_pad_time)
         self.play()
+
+
+class GoButton:
+    def __init__(self, player, statusLabel, songPaths):
+        self.player = player
+        self.statusLabel = statusLabel
+        self.songPaths = songPaths
+
+        self.player.current_time.trace("w", self.updateStatus)
+
+    def _nextAction(self):
+        state = self.player.state.get() 
+        if state == 'stop':
+            currentPath = self.player.filename_var.get()
+            try:
+                i = self.songPaths.index(currentPath) + 1
+            except ValueError:
+                i = 0
+            nextPath = self.songPaths[i]
+            return ("next song %s" % shortSongPath(nextPath,
+                                                   self.songPaths),
+                    lambda: self.player.play(nextPath))
+
+        if state == 'pause':
+            return "play", self.player.play
+
+        if state == 'play':
+            if self.player.in_post():
+                return "<nothing>", lambda: None
+            return "skip to post", self.player.skip_to_post
+        
+    def action(self):
+        desc, func = self._nextAction()
+        func()
+        
+    def updateStatus(self, *args):
+        desc, func = self._nextAction()
+        self.statusLabel.config(text=desc)
         
 
 
-def buildsonglist(root, graph, songs, player):
+def buildsonglist(root,songfiles,player):
     songlist=tk.Frame(root,bd=2,relief='raised',bg='black')
 
-    maxsfwidth=max([len(graph.label(song)) for song in songs])
+    prefixlen=len(os.path.commonprefix(songfiles))
+    # include to the last os.sep- dont crop path elements in the middle
+    prefixlen=songfiles[0].rfind(os.sep)+1 
+    maxsfwidth=max([len(x[prefixlen:]) for x in songfiles])
 
     for i,sf in enumerate(songfiles):
         b=tk.Button(songlist,text=sf[prefixlen:],width=maxsfwidth,
@@ -242,7 +294,7 @@
 
         def color_buttons(x, y, z, song=song, b=b):
             name = player.filename_var.get()
-            if name == graph.value(song, L9['showPath']):
+            if name == sf[prefixlen:]:
                 b['bg'] = 'grey50'
             else:
                 b['bg'] = 'black'
@@ -354,10 +406,11 @@
         player.current_time.trace("w",fixleft)
 
 class ControlButtons(tk.Frame):
-    def __init__(self,master):
+    def __init__(self, master, goButton, player, root):
         tk.Frame.__init__(self,master,bg='black')
-        
         self.statebuttons = {} # lowercased name : Button
+        self.goButton = goButton
+        self.player = player
         for tag, txt,cmd,key in [
             ('stop',
              'Stop\nC-s', player.stop, "<Control-s>"),
@@ -368,17 +421,18 @@
              "<Control-i>"),
             ('skip to post',
              'Skip to Post\nC-t', player.skip_to_post, "<Control-t>"),
+            ('go', 'Go\nspace', self.goButton.action, "<Key-space>"),
             ]:
             b = tk.Button(self, text=txt, command=cmd,
                           font='arial 16 bold',
                           height=3,**appstyle)
-            b.pack(side='left', fill='x', expand=1)
+            b.pack(side='left', fill='both', expand=True)
             # keyboard bindings
             root.bind(key, lambda evt, cmd=cmd: cmd())
             self.statebuttons[tag] = b
 
     def update_state_buttons(self,*args):
-        state = player.state.get()
+        state = self.player.state.get()
 
         if state in ('stop', 'pause'):
             self.statebuttons['pause']['text'] = 'Play\nC-p'
@@ -397,52 +451,62 @@
                 button['bg'] = colors.get(name, 'black')
             else:
                 button['bg'] = 'black'
+        self.goButton.updateStatus()
 
 ############################
-        
-parser=OptionParser()
 
-(options,songfiles)=parser.parse_args()
-
-graph = showconfig.getGraph()
 
 if len(songfiles)<1:
-    graph = showconfig.getGraph()
-    playList = graph.value(L9['show/dance2007'], L9['playList'])
-    songs = list(graph.items(playList))
-else:
-    raise NotImplementedError("don't know how to make rdf song nodes from cmdline song paths")
+    songfiles = [f for f in os.listdir(showconfig.musicDir())
+                 if f.endswith('wav')]
+    songfiles.sort()
 
-root=tk.Tk()
-root.wm_title("ascoltami")
-#root.wm_geometry("+1270+440")
-toplevelat("ascoltami", root)
-root.config(bg="black")
-player=Player(None,None)
+    (options, songfiles) = parser.parse_args()
 
-songlist = buildsonglist(root, graph, songs, player)
+songlist = buildsonglist(root,songfiles,player)
 songlist.pack(fill='both',exp=1)
 
-f2 = tk.Frame(bg='black')
-buts = ControlButtons(f2)
-buts.pack(side='top',fill='x')
+    root=tk.Tk()
+    root.wm_title("ascoltami")
+    toplevelat("ascoltami", root)
+    root.config(bg="black")
+    player=Player()
+
+    songlist = buildsonglist(root, songfiles, player)
 
-player.state.trace_variable('w', buts.update_state_buttons)
-buts.update_state_buttons()
+    seeker = Seeker(root, player)
+    
+    goRow = tk.Frame(root)
+    tk.Label(goRow, text="Go button action:",
+             font='arial 9', **appstyle).pack(side='left', fill='both')
+    goStatus = tk.Label(goRow, font='arial 12 bold', **appstyle)
+    goStatus.config(bg='#800000', fg='white')
+    goStatus.pack(side='left', expand=True, fill='x')
 
-seeker = Seeker(f2,player)
-seeker.pack(fill='x',exp=1)
-f2.pack(side='bottom',fill='x')
+    go = GoButton(player, goStatus, songfiles)
+    
+    buts = ControlButtons(root, go, player, root)
 
-tksupport.install(root,ms=10)
+    songlist.pack(fill='both', expand=True)
+    buts.pack(side='top', fill='x')
+    seeker.pack(side='top', fill='x')
+    goRow.pack(side='top', fill='x')
+
+    player.state.trace_variable('w', buts.update_state_buttons)
+    buts.update_state_buttons()
+
+    tksupport.install(root,ms=10)
 
-try:
-    reactor.listenTCP(networking.musicPort(),server.Site(XMLRPCServe(player)))
-    print "started server on %s" % networking.musicPort()
-except CannotListenError:
-    print "no server started- %s is in use" % networking.musicPort()
+    try:
+        reactor.listenTCP(networking.musicPort(),server.Site(XMLRPCServe(player)))
+        print "started server on %s" % networking.musicPort()
+    except CannotListenError:
+        print "no server started- %s is in use" % networking.musicPort()
 
-root.bind("<Destroy>",lambda ev: reactor.stop)
-root.protocol('WM_DELETE_WINDOW', reactor.stop)
+    root.bind("<Destroy>",lambda ev: reactor.stop)
+    root.protocol('WM_DELETE_WINDOW', reactor.stop)
 
-reactor.run()
+    reactor.run()
+    
+if __name__ == '__main__':
+    main()