# HG changeset patch # User Goffi # Date 1327257485 -3600 # Node ID e19a8de8b3de4c725b3aac8d418e62fed3b47e4e # Parent adecb2566b53c53f2c2fe9a27111eaefcc0a8b6d radio collective first draft diff -r adecb2566b53 -r e19a8de8b3de browser_side/panels.py --- 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""" diff -r adecb2566b53 -r e19a8de8b3de browser_side/radiocol.py --- /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 + +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 . +""" + +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) + diff -r adecb2566b53 -r e19a8de8b3de libervia.py --- 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]: diff -r adecb2566b53 -r e19a8de8b3de libervia.tac --- 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()