changeset 127:e19a8de8b3de

radio collective first draft
author Goffi <goffi@goffi.org>
date Sun, 22 Jan 2012 19:38:05 +0100
parents adecb2566b53
children 2849ec993d89
files browser_side/panels.py browser_side/radiocol.py libervia.py libervia.tac
diffstat 4 files changed, 176 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/browser_side/panels.py	Thu Jan 05 00:43:13 2012 +0100
+++ b/browser_side/panels.py	Sun Jan 22 19:38:05 2012 +0100
@@ -42,6 +42,7 @@
 from pyjamas import Window
 from pyjamas import DOM
 from card_game import CardPanel
+from radiocol import RadioColPanel
 from menu import Menu
 from jid import JID
 from tools import html_sanitize
@@ -732,6 +733,10 @@
             self.tarot_panel = CardPanel(self, referee, players, self.nick)
             self.vpanel.insert(self.tarot_panel, 0)
             self.vpanel.setCellHeight(self.tarot_panel, self.tarot_panel.getHeight())
+        elif game_type=="RadioCol":
+            self.radiocol_panel = RadioColPanel(self, referee, self.nick)
+            self.vpanel.insert(self.radiocol_panel, 0)
+            self.vpanel.setCellHeight(self.radiocol_panel, self.radiocol_panel.getHeight())
     
     def getGame(self, game_type):
         """Return class managing the game type"""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/browser_side/radiocol.py	Sun Jan 22 19:38:05 2012 +0100
@@ -0,0 +1,120 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+"""
+Libervia: a Salut à Toi frontend
+Copyright (C) 2011  Jérôme Poisson <goffi@goffi.org>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""
+
+import pyjd # this is dummy in pyjs
+from pyjamas.ui.VerticalPanel import VerticalPanel
+from pyjamas.ui.HorizontalPanel import HorizontalPanel
+from pyjamas.ui.SimplePanel import SimplePanel
+from pyjamas.ui.FormPanel import FormPanel
+from pyjamas.ui.DockPanel import DockPanel
+from pyjamas.ui.NamedFrame import NamedFrame
+from pyjamas.ui.FileUpload import FileUpload
+from pyjamas.ui.Label import Label
+from pyjamas.ui.Button import Button
+from pyjamas.ui.ClickListener import ClickHandler
+from pyjamas.ui.MouseListener import MouseHandler
+from pyjamas import Window
+
+from jid import JID
+from tools import html_sanitize
+
+
+class MetadataPanel(VerticalPanel):
+
+    def __init__(self):
+        VerticalPanel.__init__(self)
+        self.artist = Label("artist:")
+        self.album = Label("album:")
+        self.title = Label("title:")
+        self.add(self.artist)
+        self.add(self.album)
+        self.add(self.title)
+
+class ControlPanel(FormPanel):
+    """Panel used to show controls to add a song, or vote for the current one"""
+
+    def __init__(self):
+        FormPanel.__init__(self)
+        self.setEncoding(FormPanel.ENCODING_MULTIPART)
+        self.setMethod(FormPanel.METHOD_POST)
+        self.setAction("upload") # set this as appropriate
+        #self.setTarget("results")
+        vPanel = VerticalPanel()
+
+        hPanel = HorizontalPanel()
+        hPanel.setSpacing(5)
+        self.field = FileUpload()
+        self.field.setName("song")
+        hPanel.add(self.field)
+
+        hPanel.add(Button("Upload song", getattr(self, "onBtnClick")))
+
+        vPanel.add(hPanel)
+
+        results = NamedFrame("results")
+        vPanel.add(results)
+
+        self.add(vPanel)
+        self.addFormHandler(self)
+
+    def onBtnClick(self):
+        self.submit()
+    
+    def onSubmit(self, event):
+        pass
+
+    def onSubmitComplete(self, event):
+        result = event.getResults()
+        if result == "OK":
+            Window.alert('Your song has been added to queue')
+        elif result == "KO":
+            Window.alert('Something went wrong during your song upload')
+        else:
+            Window.alert('Submit error: %s' % result)
+
+class RadioColPanel(HorizontalPanel, ClickHandler):
+
+    def __init__(self, parent, referee, player_nick):
+        HorizontalPanel.__init__(self)
+        ClickHandler.__init__(self)
+        self._parent = parent
+        self.referee = referee
+        self.setStyleName("radiocolPanel")
+        
+        # Now we set up the layout
+        self.left_panel = VerticalPanel()
+        self.add(self.left_panel)
+        self.right_panel = DockPanel()
+        self.metadata_panel = MetadataPanel()
+        self.right_panel.add(self.metadata_panel, DockPanel.CENTER)
+        self.control_panel = ControlPanel()
+        self.right_panel.add(self.control_panel, DockPanel.SOUTH)
+        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.left_panel.add(Label("Musique 3"))
+        self.left_panel.add(Label("Musique 4"))
+        self.left_panel.add(Label("Musique 5"))
+
+        
+        self.addClickListener(self)
+
--- a/libervia.py	Thu Jan 05 00:43:13 2012 +0100
+++ b/libervia.py	Sun Jan 22 19:38:05 2012 +0100
@@ -241,6 +241,8 @@
              name == 'tarotGameYourTurn' or \
              name == 'tarotGameScore':
             self._tarotGameGenericCb(name, args[0], args[1:])
+        elif name == 'radiocolStarted':
+            self._radioColStartedCb(*args)
         elif name == 'subscribe':
             self._subscribeCb(*args)
         elif name == 'contactDeleted':
@@ -310,8 +312,6 @@
             other = _to if _from.bare == self.whoami.bare else _from
             self.contact_panel.setContactMessageWaiting(other.bare, True)
             
-
-
     def _presenceUpdateCb(self, entity, show, priority, statuses):
         _entity = JID(entity)
         #XXX: QnD way to get our status
@@ -327,6 +327,8 @@
         chat_panel.setUserNick(user_nick)
         if _target.node.startswith('sat_tarot_'): #XXX: it's not really beautiful, but it works :)
             self.addTab(chat_panel, "Tarot")
+        elif _target.node.startswith('sat_radiocol_'):
+            self.addTab(chat_panel, "Radio collective")
         else:
             self.addTab(chat_panel, _target.node)
         chat_panel.setPresents(room_nicks)
@@ -353,6 +355,11 @@
             if isinstance(lib_wid,panels.ChatPanel) and lib_wid.type == 'group' and lib_wid.target.bare == room_jid:
                 getattr(lib_wid.getGame("Tarot"), event_name)(*args) 
 
+    def _radioColStartedCb(self, room_jid, referee):
+        for lib_wid in self.libervia_widgets:
+            if isinstance(lib_wid,panels.ChatPanel) and lib_wid.type == 'group' and lib_wid.target.bare == room_jid:
+                lib_wid.startGame("RadioCol", referee)
+    
     def _getPresenceStatusCb(self, presence_data):
         for entity in presence_data:
             for resource in presence_data[entity]:
--- a/libervia.tac	Thu Jan 05 00:43:13 2012 +0100
+++ b/libervia.tac	Sun Jan 22 19:38:05 2012 +0100
@@ -43,10 +43,9 @@
 from sat_frontends.bridge.DBus import DBusBridgeFrontend,BridgeExceptionNoService
 from email.mime.text import MIMEText
 from logging import debug, info, warning, error
-import re
-import glob
-import os.path
-import sys
+import re, glob
+import os.path, sys
+import tempfile, shutil, uuid
 from server_side.blog import MicroBlog
 from zope.interface import Interface, Attribute, implements
 
@@ -598,8 +597,6 @@
 
     def connectionError(self, error_type, profile):
         assert(self.register) #register must be plugged
-        import pdb
-        pdb.set_trace()
         request = self.register.getWaitingRequest(profile)
         if request: #The user is trying to log in
             if error_type == "AUTH_ERROR":
@@ -622,13 +619,36 @@
         self.request = request
         return jsonrpc.JSONRPC.render(self, request)
 
+class UploadManager(Resource):
+    """This class manage the upload of a file
+    It redirect the stream to SàT core backend"""
+    isLeaf = True
+
+    def __init__(self, sat_host):
+        self.sat_host=sat_host
+        self.upload_dir = tempfile.mkdtemp()
+        self.sat_host.addCleanup(shutil.rmtree, self.upload_dir)
+
+    def render(self, request):
+        """
+        Render method with some hacks:
+           - if login is requested, try to login with form data
+           - 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())
+        with open(os.path.join(self.upload_dir, filename),'w') as f:
+            f.write(request.args['song'][0])
+        return "OK"
 
 class Libervia(service.Service):
    
     def __init__(self):
+        self._cleanup = []
         root = ProtectedFile(LIBERVIA_DIR) 
         self.signal_handler = SignalHandler(self)
         _register = Register(self)
+        _upload = UploadManager(self)
         self.signal_handler.plugRegister(_register)
         self.sessions = {} #key = session value = user
         self.prof_connected = set() #Profiles connected
@@ -647,13 +667,15 @@
             self.bridge.register(signal_name, self.signal_handler.getGenericCb(signal_name))
         #plugins
         for signal_name in ['personalEvent', 'roomJoined', 'roomUserJoined', 'roomUserLeft', 'tarotGameStarted', 'tarotGameNew', 'tarotGameChooseContrat',
-                            'tarotGameShowCards', 'tarotGameInvalidCards', 'tarotGameCardsPlayed', 'tarotGameYourTurn', 'tarotGameScore']:
+                            'tarotGameShowCards', 'tarotGameInvalidCards', 'tarotGameCardsPlayed', 'tarotGameYourTurn', 'tarotGameScore', 
+                            'radiocolStarted']:
             self.bridge.register(signal_name, self.signal_handler.getGenericCb(signal_name), "plugin")
         self.media_dir = self.bridge.getConfig('','media_dir')
         self.local_dir = self.bridge.getConfig('','local_dir')
         root.putChild('json_signal_api', self.signal_handler)
         root.putChild('json_api', MethodHandler(self))
         root.putChild('register_api', _register)
+        root.putChild('upload', _upload)
         root.putChild('blog', MicroBlog(self))
         root.putChild('css', ProtectedFile("server_css/"))
         root.putChild(os.path.dirname(MEDIA_DIR), ProtectedFile(self.media_dir))
@@ -661,8 +683,21 @@
         self.site = server.Site(root)
         self.site.sessionFactory = LiberviaSession
 
+    def addCleanup(self, callback, *args, **kwargs):
+        """Add cleaning method to call when service is stopped
+        cleaning method will be called in reverse order of they insertion
+        @param callback: callable to call on service stop
+        @param *args: list of arguments of the callback
+        @param **kwargs: list of keyword arguments of the callback"""
+        self._cleanup.insert(0, (callback, args, kwargs))
+
     def startService(self):
         reactor.listenTCP(8080, self.site)
+
+    def stopService(self):
+        print "launching cleaning methods"
+        for callback, args, kwargs in self._cleanup:
+            callback(*args, **kwargs)
     
     def run(self):
         reactor.run()