changeset 129:dd0d39ae7d24

RadioCol: song preloading + fonctionnal players
author Goffi <goffi@goffi.org>
date Sun, 29 Jan 2012 00:15:04 +0100
parents 2849ec993d89
children 6576c5a90060
files browser_side/radiocol.py libervia.tac public/libervia.css
diffstat 3 files changed, 126 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/browser_side/radiocol.py	Mon Jan 23 00:15:19 2012 +0100
+++ b/browser_side/radiocol.py	Sun Jan 29 00:15:04 2012 +0100
@@ -23,6 +23,7 @@
 from pyjamas.ui.VerticalPanel import VerticalPanel
 from pyjamas.ui.HorizontalPanel import HorizontalPanel
 from pyjamas.ui.SimplePanel import SimplePanel
+from pyjamas.ui.FlexTable import FlexTable
 from pyjamas.ui.FormPanel import FormPanel
 from pyjamas.ui.NamedFrame import NamedFrame
 from pyjamas.ui.FileUpload import FileUpload
@@ -33,27 +34,52 @@
 from pyjamas.ui.Hidden import Hidden
 from pyjamas.ui.HTML import HTML
 from pyjamas import Window
+from pyjamas.Timer import Timer
+from __pyjamas__ import JS
 
 from jid import JID
 from tools import html_sanitize
 
 
-class MetadataPanel(VerticalPanel):
+class MetadataPanel(FlexTable):
 
     def __init__(self):
-        VerticalPanel.__init__(self)
-        self.title = Label("title:")
-        self.artist = Label("artist:")
-        self.album = Label("album:")
-        self.add(self.title)
-        self.add(self.artist)
-        self.add(self.album)
+        FlexTable.__init__(self)
+        title_lbl =  Label("title:")
+        title_lbl.setStyleName('radiocol_metadata_lbl')
+        artist_lbl = Label("artist:")
+        artist_lbl.setStyleName('radiocol_metadata_lbl')
+        album_lbl = Label("album:")
+        album_lbl.setStyleName('radiocol_metadata_lbl')
+        self.title =  Label("")
+        self.title.setStyleName('radiocol_metadata')
+        self.artist = Label("")
+        self.artist.setStyleName('radiocol_metadata')
+        self.album = Label("")
+        self.album.setStyleName('radiocol_metadata')
+        self.setWidget(0,0,title_lbl)
+        self.setWidget(1,0,artist_lbl)
+        self.setWidget(2,0,album_lbl)
+        self.setWidget(0,1,self.title)
+        self.setWidget(1,1,self.artist)
+        self.setWidget(2,1,self.album)
+        self.setStyleName("radiocol_metadata_pnl")
+
+    def setTitle(self, title):
+        self.title.setText(title)
+
+    def setArtist(self, artist):
+        self.artist.setText(artist)
+
+    def setAlbum(self, album):
+        self.album.setText(album)
 
 class ControlPanel(FormPanel):
     """Panel used to show controls to add a song, or vote for the current one"""
 
     def __init__(self, referee):
         FormPanel.__init__(self)
+        self._timer = Timer(notify=self._timeCb)
         self.setEncoding(FormPanel.ENCODING_MULTIPART)
         self.setMethod(FormPanel.METHOD_POST)
         self.setAction("upload") # set this as appropriate
@@ -67,6 +93,8 @@
 
         hPanel.add(Button("Upload song", getattr(self, "onBtnClick")))
 
+        self.status = Label()
+
         vPanel.add(hPanel)
         
         #We need to know the referee
@@ -75,6 +103,9 @@
 
         self.add(vPanel)
         self.addFormHandler(self)
+    
+    def _timeCb(self, timer):
+        self.status.setText('')
 
     def onBtnClick(self):
         self.submit()
@@ -85,12 +116,51 @@
     def onSubmitComplete(self, event):
         result = event.getResults()
         if result == "OK":
-            Window.alert('Your song has been added to queue')
+            self.status.setText('Your song has been added to queue')
+            self.status.setStyleName('radiocol_upload_status_ok')
+            self._timer.schedule(5000)
         elif result == "KO":
-            Window.alert('Something went wrong during your song upload')
+            self.status.setText('Something went wrong during your song upload')
+            self.status.setStyleName('radiocol_upload_status_ko')
         else:
             Window.alert('Submit error: %s' % result)
 
+class Player(HTML):
+
+    def __init__(self, player_id, metadata_panel):
+        HTML.__init__(self)
+        self._id = player_id
+        self.metadata = metadata_panel
+        self.title=""
+        self.artist=""
+        self.album=""
+        self.filename = None
+        self.played = False #True when song is playing/played, become False on preload
+
+    def preload(self, filename, title, artist, album):
+        """preload the song but doesn't play it"""
+        self.filename = filename
+        self.title = title
+        self.artist = artist
+        self.album = album
+        self.played = False
+        self.setHTML('<audio id="%s" style="display: none" preload="auto" src="radiocol/%s" />' % (self._id, html_sanitize(filename)))
+        print "preloading %s in %s" % (title, self._id)
+       
+    def play(self):
+        """actually play the song"""
+        self.played = True
+        self.metadata.setTitle(self.title)
+        self.metadata.setArtist(self.artist)
+        self.metadata.setAlbum(self.album)
+
+        JS("""
+        var player = top.document.getElementById(this._id);
+        player.play();
+        """)
+        
+
+
 class RadioColPanel(HorizontalPanel, ClickHandler):
 
     def __init__(self, parent, referee, player_nick):
@@ -99,9 +169,12 @@
         self._parent = parent
         self.referee = referee
         self.setStyleName("radiocolPanel")
+        self.setHeight('30%')
         
         # Now we set up the layout
         self.left_panel = VerticalPanel()
+        self.left_panel.setStyleName("radiocol_left_panel")
+        self.left_panel.setHeight('100%')
         self.add(self.left_panel)
         self.right_panel = VerticalPanel()
         self.metadata_panel = MetadataPanel()
@@ -110,14 +183,31 @@
         self.right_panel.add(self.control_panel)
         self.add(self.right_panel)
         #self.right_panel.setBorderWidth(1)
-        self.left_panel.add(Label("Musique 1"))
-        self.left_panel.add(Label("Musique 2"))
-        self.audio = HTML("")
-        self.right_panel.add(self.audio)
-
-        
+        self.next_song_1 = Label()
+        self.next_song_1.setStyleName("radiocol_next_song")
+        self.next_song_2 = Label()
+        self.next_song_2.setStyleName("radiocol_next_song")
+        self.left_panel.add(self.next_song_1)
+        self.left_panel.add(self.next_song_2)
+        self.players = [Player("player_%d" % i, self.metadata_panel) for i in range(4)]
+        self.current_player = None
+        for player in self.players:
+            self.right_panel.add(player)
         self.addClickListener(self)
     
     def radiocolPreload(self, filename, title, artist, album):
-        self.audio.setHTML('<audio preload="auto" controls="controls" src="radiocol/%s" />' % html_sanitize(filename))
+        self.next_song_1.setText(self.next_song_2.getText())
+        self.next_song_2.setText(title)
+        preloaded = False
+        for player in self.players:
+            if not player.filename or \
+               (player.played and player != self.current_player):
+                #if player has no file loaded, or it has already played its song
+                #we use it to preload the next one
+                player.preload(filename, title, artist, album)
+                preloaded = True
+                break
+        if not preloaded:
+            print("WARNING: Can't preload song, we are getting too many songs to preload, we shouldn't have more than 2 at once")
 
+
--- a/libervia.tac	Mon Jan 23 00:15:19 2012 +0100
+++ b/libervia.tac	Sun Jan 29 00:15:04 2012 +0100
@@ -640,7 +640,7 @@
            - except login, every method is jsonrpc
            - user doesn't need to be authentified for isRegistered, but must be for all other methods
         """
-        filename = str(uuid.uuid4())
+        filename = "%s.ogg" % str(uuid.uuid4()) #XXX: chromium doesn't seem to play song without the .ogg extension, even with audio/ogg mime-type
         filepath = os.path.join(self.upload_dir, filename)
         with open(filepath,'w') as f:
             f.write(request.args['song'][0])
--- a/public/libervia.css	Mon Jan 23 00:15:19 2012 +0100
+++ b/public/libervia.css	Sun Jan 29 00:15:04 2012 +0100
@@ -851,6 +851,24 @@
     font-weight: bold;
 }
 
+/* Radiocol */
+
+.radiocol_left_panel {
+    min-width: 80px;
+    margin: 5px;
+    border-right-style: dotted;
+    border-right-width: 2px;
+}
+
+.radiocol_metadata_lbl {
+    font-weight: bold;
+}
+
+.radiocol_next_song {
+    margin-right: 5px;
+    font-style:italic;
+}
+
 /* Drag and drop */
 
 .dragover {