comparison src/plugins/plugin_misc_radiocol.py @ 717:358018c5c398

plugins (games): more factorization and flexibility for launching and joining games: - "MUC user joined", "MUC user left" and class XMPPHandler are managed directly in RoomGame - renamed __init__ parameters 'player_init_data' to 'player_init' and 'options' to 'game_init' - pass the players list in radiocol method 'createGame' and signal 'radiocolStarted' (needed for invitation system and for UI players identification) - added some parameters to manage who can invite, who can join, who to wait for... managed with check***Auth methods - joining a game that is already launched may be possible, regarding these parameters and the invitation list - leave and join a game again is partly managed: new tarot round is launched, we should keep playing the same round instead
author souliane <souliane@mailoo.org>
date Thu, 21 Nov 2013 15:49:53 +0100
parents ecc5a5b34ee1
children 074970227bc0
comparison
equal deleted inserted replaced
716:30eb49e4e05d 717:358018c5c398
20 from logging import debug, info, warning, error 20 from logging import debug, info, warning, error
21 from twisted.words.xish import domish 21 from twisted.words.xish import domish
22 from twisted.internet import reactor 22 from twisted.internet import reactor
23 from twisted.words.protocols.jabber import jid 23 from twisted.words.protocols.jabber import jid
24 24
25 from wokkel import disco, iwokkel
26
27 from zope.interface import implements
28
29 import os.path 25 import os.path
30 from os import unlink 26 from os import unlink
31 from mutagen.oggvorbis import OggVorbis, OggVorbisHeaderError 27 from mutagen.oggvorbis import OggVorbis, OggVorbisHeaderError
32 from sat.tools.plugins.games import RoomGame 28 from sat.tools.plugins.games import RoomGame
33 try: 29
34 from twisted.words.protocols.xmlstream import XMPPHandler 30
35 except ImportError:
36 from wokkel.subprotocols import XMPPHandler
37
38 MESSAGE = '/message'
39 NC_RADIOCOL = 'http://www.goffi.org/protocol/radiocol' 31 NC_RADIOCOL = 'http://www.goffi.org/protocol/radiocol'
40 RADIOC_TAG = 'radiocol' 32 RADIOC_TAG = 'radiocol'
41 RADIOC_REQUEST = MESSAGE + '/' + RADIOC_TAG + '[@xmlns="' + NC_RADIOCOL + '"]'
42 33
43 PLUGIN_INFO = { 34 PLUGIN_INFO = {
44 "name": "Radio collective plugin", 35 "name": "Radio collective plugin",
45 "import_name": "Radiocol", 36 "import_name": "Radiocol",
46 "type": "Exp", 37 "type": "Exp",
57 class Radiocol(RoomGame): 48 class Radiocol(RoomGame):
58 49
59 def __init__(self, host): 50 def __init__(self, host):
60 info(_("Radio collective initialization")) 51 info(_("Radio collective initialization"))
61 RoomGame.__init__(self, host, PLUGIN_INFO, (NC_RADIOCOL, RADIOC_TAG), 52 RoomGame.__init__(self, host, PLUGIN_INFO, (NC_RADIOCOL, RADIOC_TAG),
62 options={'queue': [], 'upload': True, 'playing': False, 'to_delete': {}}) 53 game_init={'queue': [], 'upload': True, 'playing': False, 'to_delete': {}})
63 self.host = host 54 self.host = host
64 host.bridge.addMethod("radiocolLaunch", ".plugin", in_sign='asss', out_sign='', method=self.prepareRoom) 55 host.bridge.addMethod("radiocolLaunch", ".plugin", in_sign='asss', out_sign='', method=self.prepareRoom)
65 host.bridge.addMethod("radiocolCreate", ".plugin", in_sign='ss', out_sign='', method=self.createCollectiveGame) 56 host.bridge.addMethod("radiocolCreate", ".plugin", in_sign='sass', out_sign='', method=self.createGame)
66 host.bridge.addMethod("radiocolSongAdded", ".plugin", in_sign='sss', out_sign='', method=self.radiocolSongAdded) 57 host.bridge.addMethod("radiocolSongAdded", ".plugin", in_sign='sss', out_sign='', method=self.radiocolSongAdded)
67 host.bridge.addSignal("radiocolStarted", ".plugin", signature='sss') # room_jid, referee, profile 58 host.bridge.addSignal("radiocolPlayers", ".plugin", signature='ssass') # room_jid, referee, players, profile
59 host.bridge.addSignal("radiocolStarted", ".plugin", signature='ssass') # room_jid, referee, players, profile
68 host.bridge.addSignal("radiocolSongRejected", ".plugin", signature='sss') # room_jid, reason, profile 60 host.bridge.addSignal("radiocolSongRejected", ".plugin", signature='sss') # room_jid, reason, profile
69 host.bridge.addSignal("radiocolPreload", ".plugin", signature='ssssss') # room_jid, filename, title, artist, album, profile 61 host.bridge.addSignal("radiocolPreload", ".plugin", signature='ssssss') # room_jid, filename, title, artist, album, profile
70 host.bridge.addSignal("radiocolPlay", ".plugin", signature='sss') # room_jid, filename, profile 62 host.bridge.addSignal("radiocolPlay", ".plugin", signature='sss') # room_jid, filename, profile
71 host.bridge.addSignal("radiocolNoUpload", ".plugin", signature='ss') # room_jid, profile 63 host.bridge.addSignal("radiocolNoUpload", ".plugin", signature='ss') # room_jid, profile
72 host.bridge.addSignal("radiocolUploadOk", ".plugin", signature='ss') # room_jid, profile 64 host.bridge.addSignal("radiocolUploadOk", ".plugin", signature='ss') # room_jid, profile
73 host.trigger.add("MUC user joined", self.userJoinedTrigger)
74 65
75 def __create_preload_elt(self, sender, filename, title, artist, album): 66 def __create_preload_elt(self, sender, filename, title, artist, album):
76 preload_elt = domish.Element((None, 'preload')) 67 preload_elt = domish.Element((None, 'preload'))
77 preload_elt['sender'] = sender 68 preload_elt['sender'] = sender
78 preload_elt['filename'] = filename # XXX: the frontend should know the temporary directory where file is put 69 preload_elt['filename'] = filename # XXX: the frontend should know the temporary directory where file is put
149 return 140 return
150 141
151 #we wait more than the song length to delete the file, to manage poorly reactive networks/clients 142 #we wait more than the song length to delete the file, to manage poorly reactive networks/clients
152 reactor.callLater(length + 90, unlink, file_to_delete) # FIXME: same host trick (see above) 143 reactor.callLater(length + 90, unlink, file_to_delete) # FIXME: same host trick (see above)
153 144
154 def radiocol_game_cmd(self, mess_elt, profile): 145 def room_game_cmd(self, mess_elt, profile):
155 #FIXME: we should check sender (is it referee ?) here before accepting commands 146 #FIXME: we should check sender (is it referee ?) here before accepting commands
156 from_jid = jid.JID(mess_elt['from']) 147 from_jid = jid.JID(mess_elt['from'])
157 room_jid = jid.JID(from_jid.userhost()) 148 room_jid = jid.JID(from_jid.userhost())
158 radio_elt = mess_elt.firstChildElement() 149 radio_elt = mess_elt.firstChildElement()
159 radio_data = self.games[room_jid.userhost()] 150 radio_data = self.games[room_jid.userhost()]
160 queue = radio_data['queue'] 151 if 'queue' in radio_data:
152 queue = radio_data['queue']
161 153
162 for elt in radio_elt.elements(): 154 for elt in radio_elt.elements():
163 155
164 if elt.name == 'started': # new game created 156 if elt.name == 'started' or elt.name == 'players': # new game created
165 self.host.bridge.radiocolStarted(room_jid.userhost(), from_jid.full(), profile) 157 players = []
158 for player in elt.elements():
159 players.append(unicode(player))
160 signal = self.host.bridge.radiocolStarted if elt.name == 'started' else self.host.bridge.radiocolPlayers
161 signal(room_jid.userhost(), from_jid.full(), players, profile)
166 elif elt.name == 'preload': # a song is in queue and must be preloaded 162 elif elt.name == 'preload': # a song is in queue and must be preloaded
167 self.host.bridge.radiocolPreload(room_jid.userhost(), elt['filename'], elt['title'], elt['artist'], elt['album'], profile) 163 self.host.bridge.radiocolPreload(room_jid.userhost(), elt['filename'], elt['title'], elt['artist'], elt['album'], profile)
168 elif elt.name == 'play': 164 elif elt.name == 'play':
169 self.host.bridge.radiocolPlay(room_jid.userhost(), elt['filename'], profile) 165 self.host.bridge.radiocolPlay(room_jid.userhost(), elt['filename'], profile)
170 elif elt.name == 'song_rejected': # a song has been refused 166 elif elt.name == 'song_rejected': # a song has been refused
206 #we can now start the party :) 202 #we can now start the party :)
207 radio_data['playing'] = True 203 radio_data['playing'] = True
208 self.playNext(room_jid, profile) 204 self.playNext(room_jid, profile)
209 else: 205 else:
210 error(_('Unmanaged game element: %s') % elt.name) 206 error(_('Unmanaged game element: %s') % elt.name)
211
212 def getHandler(self, profile):
213 return RadiocolHandler(self)
214
215
216 class RadiocolHandler (XMPPHandler):
217 implements(iwokkel.IDisco)
218
219 def __init__(self, plugin_parent):
220 self.plugin_parent = plugin_parent
221 self.host = plugin_parent.host
222
223 def connectionInitialized(self):
224 self.xmlstream.addObserver(RADIOC_REQUEST, self.plugin_parent.radiocol_game_cmd, profile=self.parent.profile)
225
226 def getDiscoInfo(self, requestor, target, nodeIdentifier=''):
227 return [disco.DiscoFeature(NC_RADIOCOL)]
228
229 def getDiscoItems(self, requestor, target, nodeIdentifier=''):
230 return []