comparison src/plugins/plugin_misc_radiocol.py @ 594:e629371a28d3

Fix pep8 support in src/plugins.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Fri, 18 Jan 2013 17:55:35 +0100
parents beaf6bec2fcd
children 84a6e83157c2
comparison
equal deleted inserted replaced
593:70bae685d05c 594:e629371a28d3
41 NC_RADIOCOL = 'http://www.goffi.org/protocol/radiocol' 41 NC_RADIOCOL = 'http://www.goffi.org/protocol/radiocol'
42 RADIOC_TAG = 'radiocol' 42 RADIOC_TAG = 'radiocol'
43 RADIOC_REQUEST = MESSAGE + '/' + RADIOC_TAG + '[@xmlns="' + NC_RADIOCOL + '"]' 43 RADIOC_REQUEST = MESSAGE + '/' + RADIOC_TAG + '[@xmlns="' + NC_RADIOCOL + '"]'
44 44
45 PLUGIN_INFO = { 45 PLUGIN_INFO = {
46 "name": "Radio collective plugin", 46 "name": "Radio collective plugin",
47 "import_name": "Radiocol", 47 "import_name": "Radiocol",
48 "type": "Exp", 48 "type": "Exp",
49 "protocols": [], 49 "protocols": [],
50 "dependencies": ["XEP-0045", "XEP-0249"], 50 "dependencies": ["XEP-0045", "XEP-0249"],
51 "main": "Radiocol", 51 "main": "Radiocol",
52 "handler": "yes", 52 "handler": "yes",
53 "description": _("""Implementation of radio collective""") 53 "description": _("""Implementation of radio collective""")
54 } 54 }
55 55
56 QUEUE_LIMIT = 2 56 QUEUE_LIMIT = 2
57 57
58 58
59 class Radiocol(object): 59 class Radiocol(object):
60 60
61 def __init__(self, host): 61 def __init__(self, host):
62 info(_("Radio collective initialization")) 62 info(_("Radio collective initialization"))
63 self.host = host 63 self.host = host
64 self.radios={} 64 self.radios = {}
65 host.bridge.addMethod("radiocolLaunch", ".plugin", in_sign='ass', out_sign='', method=self.radiocolLaunch) 65 host.bridge.addMethod("radiocolLaunch", ".plugin", in_sign='ass', out_sign='', method=self.radiocolLaunch)
66 host.bridge.addMethod("radiocolCreate", ".plugin", in_sign='ss', out_sign='', method=self.radiocolCreate) 66 host.bridge.addMethod("radiocolCreate", ".plugin", in_sign='ss', out_sign='', method=self.radiocolCreate)
67 host.bridge.addMethod("radiocolSongAdded", ".plugin", in_sign='sss', out_sign='', method=self.radiocolSongAdded) 67 host.bridge.addMethod("radiocolSongAdded", ".plugin", in_sign='sss', out_sign='', method=self.radiocolSongAdded)
68 host.bridge.addSignal("radiocolStarted", ".plugin", signature='sss') #room_jid, referee, profile 68 host.bridge.addSignal("radiocolStarted", ".plugin", signature='sss') # room_jid, referee, profile
69 host.bridge.addSignal("radiocolSongRejected", ".plugin", signature='sss') #room_jid, reason, profile 69 host.bridge.addSignal("radiocolSongRejected", ".plugin", signature='sss') # room_jid, reason, profile
70 host.bridge.addSignal("radiocolPreload", ".plugin", signature='ssssss') #room_jid, filename, title, artist, album, profile 70 host.bridge.addSignal("radiocolPreload", ".plugin", signature='ssssss') # room_jid, filename, title, artist, album, profile
71 host.bridge.addSignal("radiocolPlay", ".plugin", signature='sss') #room_jid, filename, profile 71 host.bridge.addSignal("radiocolPlay", ".plugin", signature='sss') # room_jid, filename, profile
72 host.bridge.addSignal("radiocolNoUpload", ".plugin", signature='ss') #room_jid, profile 72 host.bridge.addSignal("radiocolNoUpload", ".plugin", signature='ss') # room_jid, profile
73 host.bridge.addSignal("radiocolUploadOk", ".plugin", signature='ss') #room_jid, profile 73 host.bridge.addSignal("radiocolUploadOk", ".plugin", signature='ss') # room_jid, profile
74 host.trigger.add("MUC user joined", self.userJoinedTrigger) 74 host.trigger.add("MUC user joined", self.userJoinedTrigger)
75 75
76 def createRadiocolElt(self, to_jid, type="normal"): 76 def createRadiocolElt(self, to_jid, type="normal"):
77 type = "normal" if to_jid.resource else "groupchat" 77 type = "normal" if to_jid.resource else "groupchat"
78 elt = domish.Element((None,'message')) 78 elt = domish.Element((None, 'message'))
79 elt["to"] = to_jid.full() 79 elt["to"] = to_jid.full()
80 elt["type"] = type 80 elt["type"] = type
81 elt.addElement((NC_RADIOCOL, RADIOC_TAG)) 81 elt.addElement((NC_RADIOCOL, RADIOC_TAG))
82 return elt 82 return elt
83 83
84 def __create_started_elt(self): 84 def __create_started_elt(self):
85 """Create a game_started domish element""" 85 """Create a game_started domish element"""
86 started_elt = domish.Element((None,'started')) 86 started_elt = domish.Element((None, 'started'))
87 return started_elt 87 return started_elt
88 88
89 def __create_preload_elt(self, sender, filename, title, artist, album): 89 def __create_preload_elt(self, sender, filename, title, artist, album):
90 preload_elt = domish.Element((None,'preload')) 90 preload_elt = domish.Element((None, 'preload'))
91 preload_elt['sender'] = sender 91 preload_elt['sender'] = sender
92 preload_elt['filename'] = filename #XXX: the frontend should know the temporary directory where file is put 92 preload_elt['filename'] = filename # XXX: the frontend should know the temporary directory where file is put
93 preload_elt['title'] = title 93 preload_elt['title'] = title
94 preload_elt['artist'] = artist 94 preload_elt['artist'] = artist
95 preload_elt['album'] = album 95 preload_elt['album'] = album
96 return preload_elt 96 return preload_elt
97 97
98
99 def userJoinedTrigger(self, room, user, profile): 98 def userJoinedTrigger(self, room, user, profile):
100 """This trigger is used to check if we are waiting people in this room, 99 """This trigger is used to check if we are waiting people in this room,
101 and to create a game if everybody is here""" 100 and to create a game if everybody is here"""
102 room_jid = room.occupantJID.userhost() 101 room_jid = room.occupantJID.userhost()
103 if self.radios.has_key(room_jid) and self.radios[room_jid]["referee"] == room.occupantJID.full(): 102 if room_jid in self.radios and self.radios[room_jid]["referee"] == room.occupantJID.full():
104 #we are in a radiocol room, let's start the party ! 103 #we are in a radiocol room, let's start the party !
105 mess = self.createRadiocolElt(jid.JID(room_jid+'/'+user.nick)) 104 mess = self.createRadiocolElt(jid.JID(room_jid + '/' + user.nick))
106 mess.firstChildElement().addChild(self.__create_started_elt()) 105 mess.firstChildElement().addChild(self.__create_started_elt())
107 self.host.profiles[profile].xmlstream.send(mess) 106 self.host.profiles[profile].xmlstream.send(mess)
108 return True 107 return True
109 108
110 def radiocolLaunch(self, occupants, profile_key='@DEFAULT@'): 109 def radiocolLaunch(self, occupants, profile_key='@DEFAULT@'):
119 def radiocolRoomJoined(room): 118 def radiocolRoomJoined(room):
120 print "radiocolRoomJoined" 119 print "radiocolRoomJoined"
121 _room_jid = room.occupantJID.userhostJID() 120 _room_jid = room.occupantJID.userhostJID()
122 self.radiocolCreate(_room_jid.userhost(), profile_key=profile) 121 self.radiocolCreate(_room_jid.userhost(), profile_key=profile)
123 for occupant in occupants: 122 for occupant in occupants:
124 self.host.plugins["XEP-0249"].invite(jid.JID(occupant), room.occupantJID.userhostJID(), {"game":"Radiocol"}, profile) 123 self.host.plugins["XEP-0249"].invite(jid.JID(occupant), room.occupantJID.userhostJID(), {"game": "Radiocol"}, profile)
125 124
126 def after_init(ignore): 125 def after_init(ignore):
127 room_name = "sat_radiocol_%s" % self.host.plugins["XEP-0045"].getUniqueName(profile_key) 126 room_name = "sat_radiocol_%s" % self.host.plugins["XEP-0045"].getUniqueName(profile_key)
128 print "\n\n===> room_name:", room_name 127 print "\n\n===> room_name:", room_name
129 muc_service = None 128 muc_service = None
151 150
152 def radiocolCreate(self, room_jid_param, profile_key='@DEFAULT@'): 151 def radiocolCreate(self, room_jid_param, profile_key='@DEFAULT@'):
153 """Create a new game 152 """Create a new game
154 @param room_jid_param: jid of the room 153 @param room_jid_param: jid of the room
155 @param profile_key: %(doc_profile_key)s""" 154 @param profile_key: %(doc_profile_key)s"""
156 debug (_("Creating Radiocol")) 155 debug(_("Creating Radiocol"))
157 room_jid = jid.JID(room_jid_param) 156 room_jid = jid.JID(room_jid_param)
158 profile = self.host.memory.getProfileName(profile_key) 157 profile = self.host.memory.getProfileName(profile_key)
159 if not profile: 158 if not profile:
160 error (_("profile %s is unknown") % profile_key) 159 error(_("profile %s is unknown") % profile_key)
161 return 160 return
162 if self.radios.has_key(room_jid): 161 if room_jid in self.radios:
163 warning (_("Radiocol already started in room %s") % room_jid.userhost()) 162 warning(_("Radiocol already started in room %s") % room_jid.userhost())
164 else: 163 else:
165 room_nick = self.host.plugins["XEP-0045"].getRoomNick(room_jid.userhost(), profile) 164 room_nick = self.host.plugins["XEP-0045"].getRoomNick(room_jid.userhost(), profile)
166 if not room_nick: 165 if not room_nick:
167 error ('Internal error') 166 error('Internal error')
168 return 167 return
169 referee = room_jid.userhost() + '/' + room_nick 168 referee = room_jid.userhost() + '/' + room_nick
170 self.radios[room_jid.userhost()] = {'referee':referee, 'queue':[], 'upload':True, 'playing': False, 'occupants_data':{}, 'to_delete':{}} 169 self.radios[room_jid.userhost()] = {'referee': referee, 'queue': [], 'upload': True, 'playing': False, 'occupants_data': {}, 'to_delete': {}}
171 mess = self.createRadiocolElt(jid.JID(room_jid.userhost())) 170 mess = self.createRadiocolElt(jid.JID(room_jid.userhost()))
172 mess.firstChildElement().addChild(self.__create_started_elt()) 171 mess.firstChildElement().addChild(self.__create_started_elt())
173 self.host.profiles[profile].xmlstream.send(mess) 172 self.host.profiles[profile].xmlstream.send(mess)
174 173
175 def radiocolSongAdded(self, referee, song_path, profile): 174 def radiocolSongAdded(self, referee, song_path, profile):
187 return 186 return
188 try: 187 try:
189 song = OggVorbis(song_path) 188 song = OggVorbis(song_path)
190 except OggVorbisHeaderError: 189 except OggVorbisHeaderError:
191 #this file is not ogg vorbis, we reject it 190 #this file is not ogg vorbis, we reject it
192 unlink(song_path) # FIXME: same host trick (see note above) 191 unlink(song_path) # FIXME: same host trick (see note above)
193 self.host.bridge.radiocolSongRejected(jid.JID(referee).userhost(), \ 192 self.host.bridge.radiocolSongRejected(jid.JID(referee).userhost(),
194 "Uploaded file is not Ogg Vorbis song, only Ogg Vorbis songs are acceptable", profile) 193 "Uploaded file is not Ogg Vorbis song, only Ogg Vorbis songs are acceptable", profile)
195 """mess = self.createRadiocolElt(jid.JID(referee)) 194 """mess = self.createRadiocolElt(jid.JID(referee))
196 reject_elt = mess.firstChildElement().addElement(('','song_rejected')) 195 reject_elt = mess.firstChildElement().addElement(('','song_rejected'))
197 reject_elt['sender'] = client.jid 196 reject_elt['sender'] = client.jid
198 reject_elt['reason'] = "Uploaded file is not Ogg Vorbis song, only Ogg Vorbis songs are acceptable" 197 reject_elt['reason'] = "Uploaded file is not Ogg Vorbis song, only Ogg Vorbis songs are acceptable"
202 title = song.get("title", ["Unknown"])[0] 201 title = song.get("title", ["Unknown"])[0]
203 artist = song.get("artist", ["Unknown"])[0] 202 artist = song.get("artist", ["Unknown"])[0]
204 album = song.get("album", ["Unknown"])[0] 203 album = song.get("album", ["Unknown"])[0]
205 length = song.info.length 204 length = song.info.length
206 mess = self.createRadiocolElt(jid.JID(referee)) 205 mess = self.createRadiocolElt(jid.JID(referee))
207 added_elt = mess.firstChildElement().addElement(('','song_added')) 206 added_elt = mess.firstChildElement().addElement(('', 'song_added'))
208 added_elt['filename'] = filename = os.path.basename(song_path) 207 added_elt['filename'] = filename = os.path.basename(song_path)
209 added_elt['title'] = title 208 added_elt['title'] = title
210 added_elt['artist'] = artist 209 added_elt['artist'] = artist
211 added_elt['album'] = album 210 added_elt['album'] = album
212 added_elt['length'] = str(length) 211 added_elt['length'] = str(length)
213 self.host.profiles[profile].xmlstream.send(mess) 212 self.host.profiles[profile].xmlstream.send(mess)
214 213
215 radio_data = self.radios[jid.JID(referee).userhost()] #FIXME: referee comes from Libervia's client side, it's unsecure 214 radio_data = self.radios[jid.JID(referee).userhost()] # FIXME: referee comes from Libervia's client side, it's unsecure
216 radio_data['to_delete'][filename] = song_path #FIXME: works only because of the same host trick, see the note under the docstring 215 radio_data['to_delete'][filename] = song_path # FIXME: works only because of the same host trick, see the note under the docstring
217 216
218 def playNext(self, room_jid, profile): 217 def playNext(self, room_jid, profile):
219 """"Play next sont in queue if exists, and put a timer 218 """"Play next sont in queue if exists, and put a timer
220 which trigger after the song has been played to play next one""" 219 which trigger after the song has been played to play next one"""
221 #TODO: need to check that there are still peoples in the room 220 #TODO: need to check that there are still peoples in the room
229 radio_data['playing'] = False 228 radio_data['playing'] = False
230 return 229 return
231 230
232 filename, length = queue.pop(0) 231 filename, length = queue.pop(0)
233 mess = self.createRadiocolElt(room_jid) 232 mess = self.createRadiocolElt(room_jid)
234 play_elt = mess.firstChildElement().addElement(('','play')) 233 play_elt = mess.firstChildElement().addElement(('', 'play'))
235 play_elt['filename'] = filename 234 play_elt['filename'] = filename
236 self.host.profiles[profile].xmlstream.send(mess) 235 self.host.profiles[profile].xmlstream.send(mess)
237 236
238 if not radio_data['upload'] and len(queue) < QUEUE_LIMIT: 237 if not radio_data['upload'] and len(queue) < QUEUE_LIMIT:
239 #upload is blocked and we now have resources to get more, we reactivate it 238 #upload is blocked and we now have resources to get more, we reactivate it
240 mess = self.createRadiocolElt(room_jid) 239 mess = self.createRadiocolElt(room_jid)
241 no_upload_elt = mess.firstChildElement().addElement(('','upload_ok')) 240 no_upload_elt = mess.firstChildElement().addElement(('', 'upload_ok'))
242 self.host.profiles[profile].xmlstream.send(mess) 241 self.host.profiles[profile].xmlstream.send(mess)
243 radio_data['upload'] = True 242 radio_data['upload'] = True
244 243
245 reactor.callLater(length, self.playNext, room_jid, profile) 244 reactor.callLater(length, self.playNext, room_jid, profile)
246 try: 245 try:
248 except KeyError: 247 except KeyError:
249 error(_("INTERNAL ERROR: can't find full path of the song to delete")) 248 error(_("INTERNAL ERROR: can't find full path of the song to delete"))
250 return 249 return
251 250
252 #we wait more than the song length to delete the file, to manage poorly reactive networks/clients 251 #we wait more than the song length to delete the file, to manage poorly reactive networks/clients
253 reactor.callLater(length + 90, unlink, file_to_delete) #FIXME: same host trick (see above) 252 reactor.callLater(length + 90, unlink, file_to_delete) # FIXME: same host trick (see above)
254
255 253
256 def radiocol_game_cmd(self, mess_elt, profile): 254 def radiocol_game_cmd(self, mess_elt, profile):
257 #FIXME: we should check sender (is it referee ?) here before accepting commands 255 #FIXME: we should check sender (is it referee ?) here before accepting commands
258 from_jid = jid.JID(mess_elt['from']) 256 from_jid = jid.JID(mess_elt['from'])
259 room_jid = jid.JID(from_jid.userhost()) 257 room_jid = jid.JID(from_jid.userhost())
262 occupants_data = radio_data['occupants_data'] 260 occupants_data = radio_data['occupants_data']
263 queue = radio_data['queue'] 261 queue = radio_data['queue']
264 262
265 for elt in radio_elt.elements(): 263 for elt in radio_elt.elements():
266 264
267 if elt.name == 'started': #new game created 265 if elt.name == 'started': # new game created
268 self.host.bridge.radiocolStarted(room_jid.userhost(), from_jid.full(), profile) 266 self.host.bridge.radiocolStarted(room_jid.userhost(), from_jid.full(), profile)
269 elif elt.name == 'preload': #a song is in queue and must be preloaded 267 elif elt.name == 'preload': # a song is in queue and must be preloaded
270 self.host.bridge.radiocolPreload(room_jid.userhost(), elt['filename'], elt['title'], elt['artist'], elt['album'], profile) 268 self.host.bridge.radiocolPreload(room_jid.userhost(), elt['filename'], elt['title'], elt['artist'], elt['album'], profile)
271 elif elt.name == 'play': 269 elif elt.name == 'play':
272 self.host.bridge.radiocolPlay(room_jid.userhost(), elt['filename'], profile) 270 self.host.bridge.radiocolPlay(room_jid.userhost(), elt['filename'], profile)
273 elif elt.name == 'song_rejected': #a song has been refused 271 elif elt.name == 'song_rejected': # a song has been refused
274 self.host.bridge.radiocolSongRejected(room_jid.userhost(), elt['reason'], profile) 272 self.host.bridge.radiocolSongRejected(room_jid.userhost(), elt['reason'], profile)
275 elif elt.name == 'no_upload': 273 elif elt.name == 'no_upload':
276 self.host.bridge.radiocolNoUpload(room_jid.userhost(), profile) 274 self.host.bridge.radiocolNoUpload(room_jid.userhost(), profile)
277 elif elt.name == 'upload_ok': 275 elif elt.name == 'upload_ok':
278 self.host.bridge.radiocolUploadOk(room_jid.userhost(), profile) 276 self.host.bridge.radiocolUploadOk(room_jid.userhost(), profile)
279 elif elt.name == 'song_added': #a song has been added 277 elif elt.name == 'song_added': # a song has been added
280 #FIXME: we are KISS for the proof of concept: every song is added, to a limit of 3 in queue. 278 #FIXME: we are KISS for the proof of concept: every song is added, to a limit of 3 in queue.
281 # Need to manage some sort of rules to allow peoples to send songs 279 # Need to manage some sort of rules to allow peoples to send songs
282 280
283 if len(queue) >= QUEUE_LIMIT: 281 if len(queue) >= QUEUE_LIMIT:
284 #there are already too many songs in queue, we reject this one 282 #there are already too many songs in queue, we reject this one
285 mess = self.createRadiocolElt(room_jid) 283 mess = self.createRadiocolElt(room_jid)
286 reject_elt = mess.firstChildElement().addElement(('','song_rejected')) 284 reject_elt = mess.firstChildElement().addElement(('', 'song_rejected'))
287 reject_elt['sender'] = from_jid.resource 285 reject_elt['sender'] = from_jid.resource
288 reject_elt['reason'] = "Too many songs in queue" 286 reject_elt['reason'] = "Too many songs in queue"
289 #FIXME: add an error code 287 #FIXME: add an error code
290 self.host.profiles[profile].xmlstream.send(mess) 288 self.host.profiles[profile].xmlstream.send(mess)
291 return 289 return
294 queue.append((elt['filename'], float(elt['length']))) 292 queue.append((elt['filename'], float(elt['length'])))
295 293
296 if len(queue) >= QUEUE_LIMIT: 294 if len(queue) >= QUEUE_LIMIT:
297 #We are at the limit, we refuse new upload until next play 295 #We are at the limit, we refuse new upload until next play
298 mess = self.createRadiocolElt(room_jid) 296 mess = self.createRadiocolElt(room_jid)
299 no_upload_elt = mess.firstChildElement().addElement(('','no_upload')) 297 no_upload_elt = mess.firstChildElement().addElement(('', 'no_upload'))
300 #FIXME: add an error code 298 #FIXME: add an error code
301 self.host.profiles[profile].xmlstream.send(mess) 299 self.host.profiles[profile].xmlstream.send(mess)
302 radio_data['upload'] = False 300 radio_data['upload'] = False
303
304 301
305 mess = self.createRadiocolElt(room_jid) 302 mess = self.createRadiocolElt(room_jid)
306 preload_elt = self.__create_preload_elt(from_jid.resource, 303 preload_elt = self.__create_preload_elt(from_jid.resource,
307 elt['filename'], 304 elt['filename'],
308 elt['title'], 305 elt['title'],
314 #we have not started playing yet, and we have 2 songs in queue 311 #we have not started playing yet, and we have 2 songs in queue
315 #we can now start the party :) 312 #we can now start the party :)
316 radio_data['playing'] = True 313 radio_data['playing'] = True
317 self.playNext(room_jid, profile) 314 self.playNext(room_jid, profile)
318 else: 315 else:
319 error (_('Unmanaged game element: %s') % elt.name) 316 error(_('Unmanaged game element: %s') % elt.name)
320 317
321 def getHandler(self, profile): 318 def getHandler(self, profile):
322 return RadiocolHandler(self) 319 return RadiocolHandler(self)
320
323 321
324 class RadiocolHandler (XMPPHandler): 322 class RadiocolHandler (XMPPHandler):
325 implements(iwokkel.IDisco) 323 implements(iwokkel.IDisco)
326 324
327 def __init__(self, plugin_parent): 325 def __init__(self, plugin_parent):
328 self.plugin_parent = plugin_parent 326 self.plugin_parent = plugin_parent
329 self.host = plugin_parent.host 327 self.host = plugin_parent.host
330 328
331 def connectionInitialized(self): 329 def connectionInitialized(self):
332 self.xmlstream.addObserver(RADIOC_REQUEST, self.plugin_parent.radiocol_game_cmd, profile = self.parent.profile) 330 self.xmlstream.addObserver(RADIOC_REQUEST, self.plugin_parent.radiocol_game_cmd, profile=self.parent.profile)
333 331
334 def getDiscoInfo(self, requestor, target, nodeIdentifier=''): 332 def getDiscoInfo(self, requestor, target, nodeIdentifier=''):
335 return [disco.DiscoFeature(NC_RADIOCOL)] 333 return [disco.DiscoFeature(NC_RADIOCOL)]
336 334
337 def getDiscoItems(self, requestor, target, nodeIdentifier=''): 335 def getDiscoItems(self, requestor, target, nodeIdentifier=''):
338 return [] 336 return []
339