Mercurial > libervia-backend
comparison src/plugins/plugin_misc_radiocol.py @ 457:fbe7c9118ce4
plugin radiocol: working Radio Collective \o/
author | Goffi <goffi@goffi.org> |
---|---|
date | Sun, 29 Jan 2012 03:00:25 +0100 |
parents | ba6e1feda03e |
children | cf005701624b |
comparison
equal
deleted
inserted
replaced
456:ba6e1feda03e | 457:fbe7c9118ce4 |
---|---|
56 "main": "Radiocol", | 56 "main": "Radiocol", |
57 "handler": "yes", | 57 "handler": "yes", |
58 "description": _("""Implementation of radio collective""") | 58 "description": _("""Implementation of radio collective""") |
59 } | 59 } |
60 | 60 |
61 QUEUE_LIMIT = 2 | |
62 | |
61 | 63 |
62 class Radiocol(): | 64 class Radiocol(): |
63 | 65 |
64 def __init__(self, host): | 66 def __init__(self, host): |
65 info(_("Radio collective initialization")) | 67 info(_("Radio collective initialization")) |
69 host.bridge.addMethod("radiocolCreate", ".plugin", in_sign='ss', out_sign='', method=self.radiocolCreate) | 71 host.bridge.addMethod("radiocolCreate", ".plugin", in_sign='ss', out_sign='', method=self.radiocolCreate) |
70 host.bridge.addMethod("radiocolSongAdded", ".plugin", in_sign='sss', out_sign='', method=self.radiocolSongAdded) | 72 host.bridge.addMethod("radiocolSongAdded", ".plugin", in_sign='sss', out_sign='', method=self.radiocolSongAdded) |
71 host.bridge.addSignal("radiocolStarted", ".plugin", signature='sss') #room_jid, referee, profile | 73 host.bridge.addSignal("radiocolStarted", ".plugin", signature='sss') #room_jid, referee, profile |
72 host.bridge.addSignal("radiocolSongRejected", ".plugin", signature='sss') #room_jid, reason, profile | 74 host.bridge.addSignal("radiocolSongRejected", ".plugin", signature='sss') #room_jid, reason, profile |
73 host.bridge.addSignal("radiocolPreload", ".plugin", signature='ssssss') #room_jid, filename, title, artist, album, profile | 75 host.bridge.addSignal("radiocolPreload", ".plugin", signature='ssssss') #room_jid, filename, title, artist, album, profile |
76 host.bridge.addSignal("radiocolPlay", ".plugin", signature='sss') #room_jid, filename, profile | |
77 host.bridge.addSignal("radiocolNoUpload", ".plugin", signature='ss') #room_jid, profile | |
78 host.bridge.addSignal("radiocolUploadOk", ".plugin", signature='ss') #room_jid, profile | |
74 host.trigger.add("MUC user joined", self.userJoinedTrigger) | 79 host.trigger.add("MUC user joined", self.userJoinedTrigger) |
75 | 80 |
76 def createRadiocolElt(self, to_jid, type="normal"): | 81 def createRadiocolElt(self, to_jid, type="normal"): |
77 type = "normal" if to_jid.resource else "groupchat" | 82 type = "normal" if to_jid.resource else "groupchat" |
78 elt = domish.Element(('jabber:client','message')) | 83 elt = domish.Element(('jabber:client','message')) |
83 | 88 |
84 def __create_started_elt(self): | 89 def __create_started_elt(self): |
85 """Create a game_started domish element""" | 90 """Create a game_started domish element""" |
86 started_elt = domish.Element(('','started')) | 91 started_elt = domish.Element(('','started')) |
87 return started_elt | 92 return started_elt |
93 | |
94 def __create_preload_elt(self, sender, filename, title, artist, album): | |
95 preload_elt = domish.Element(('','preload')) | |
96 preload_elt['sender'] = sender | |
97 preload_elt['filename'] = filename #XXX: the frontend should know the temporary directory where file is put | |
98 preload_elt['title'] = title | |
99 preload_elt['artist'] = artist | |
100 preload_elt['album'] = album | |
101 return preload_elt | |
102 | |
88 | 103 |
89 def userJoinedTrigger(self, room, user, profile): | 104 def userJoinedTrigger(self, room, user, profile): |
90 """This trigger is used to check if we are waiting people in this room, | 105 """This trigger is used to check if we are waiting people in this room, |
91 and to create a game if everybody is here""" | 106 and to create a game if everybody is here""" |
92 room_jid = room.occupantJID.userhost() | 107 room_jid = room.occupantJID.userhost() |
157 error ('Internal error') | 172 error ('Internal error') |
158 return | 173 return |
159 referee = room_jid.userhost() + '/' + room_nick | 174 referee = room_jid.userhost() + '/' + room_nick |
160 status = {} | 175 status = {} |
161 occupants_data = {} | 176 occupants_data = {} |
162 self.radios[room_jid.userhost()] = {'referee':referee, 'occupants_data':occupants_data} | 177 self.radios[room_jid.userhost()] = {'referee':referee, 'queue':[], 'upload':True, 'playing': False, 'occupants_data':occupants_data} |
163 mess = self.createRadiocolElt(jid.JID(room_jid.userhost())) | 178 mess = self.createRadiocolElt(jid.JID(room_jid.userhost())) |
164 mess.firstChildElement().addChild(self.__create_started_elt()) | 179 mess.firstChildElement().addChild(self.__create_started_elt()) |
165 self.host.profiles[profile].xmlstream.send(mess) | 180 self.host.profiles[profile].xmlstream.send(mess) |
166 | 181 |
167 def radiocolSongAdded(self, referee, song_path, profile): | 182 def radiocolSongAdded(self, referee, song_path, profile): |
179 return | 194 return |
180 try: | 195 try: |
181 song = OggVorbis(song_path) | 196 song = OggVorbis(song_path) |
182 except OggVorbisHeaderError: | 197 except OggVorbisHeaderError: |
183 #this file is not ogg vorbis, we reject it | 198 #this file is not ogg vorbis, we reject it |
184 import pdb | 199 self.host.bridge.radiocolSongRejected(jid.JID(referee).userhost(), \ |
185 pdb.set_trace() | 200 "Uploaded file is not Ogg Vorbis song, only Ogg Vorbis songs are acceptable", profile) |
186 """mess = self.createRadiocolElt(jid.JID(referee)) | 201 """mess = self.createRadiocolElt(jid.JID(referee)) |
187 reject_elt = mess.firstChildElement().addElement(('','song_rejected')) | 202 reject_elt = mess.firstChildElement().addElement(('','song_rejected')) |
188 reject_elt['sender'] = client.jid | 203 reject_elt['sender'] = client.jid |
189 reject_elt['reason'] = _("Uploaded file is not Ogg Vorbis song, only Ogg Vorbis songs are acceptable") | 204 reject_elt['reason'] = "Uploaded file is not Ogg Vorbis song, only Ogg Vorbis songs are acceptable" |
190 #FIXME: add an error code | 205 #FIXME: add an error code |
191 self.host.profiles[profile].xmlstream.send(mess)""" | 206 self.host.profiles[profile].xmlstream.send(mess)""" |
192 return | 207 return |
193 title = song.get("title", ["Unknown"])[0] | 208 title = song.get("title", ["Unknown"])[0] |
194 artist = song.get("artist", ["Unknown"])[0] | 209 artist = song.get("artist", ["Unknown"])[0] |
202 added_elt['album'] = album | 217 added_elt['album'] = album |
203 added_elt['length'] = str(length) | 218 added_elt['length'] = str(length) |
204 self.host.profiles[profile].xmlstream.send(mess) | 219 self.host.profiles[profile].xmlstream.send(mess) |
205 return | 220 return |
206 | 221 |
207 | 222 def playNext(self, room_jid, profile): |
223 """"Play next sont in queue if exists, and put a timer | |
224 which trigger after the song has been played to play next one""" | |
225 #TODO: need to check that there are still peoples in the room | |
226 # and clean the datas/stop the playlist if it's not the case | |
227 radio_data = self.radios[room_jid.userhost()] | |
228 queue = radio_data['queue'] | |
229 if not queue: | |
230 #nothing left to play, we need to wait for uploads | |
231 radio_data['playing'] = False | |
232 return | |
233 | |
234 filename, length = queue.pop(0) | |
235 mess = self.createRadiocolElt(room_jid) | |
236 play_elt = mess.firstChildElement().addElement(('','play')) | |
237 play_elt['filename'] = filename | |
238 self.host.profiles[profile].xmlstream.send(mess) | |
239 | |
240 if not radio_data['upload'] and len(queue) < QUEUE_LIMIT: | |
241 #upload is blocked and we now have resources to get more, we reactivate it | |
242 mess = self.createRadiocolElt(room_jid) | |
243 no_upload_elt = mess.firstChildElement().addElement(('','upload_ok')) | |
244 self.host.profiles[profile].xmlstream.send(mess) | |
245 radio_data['upload'] = True | |
246 | |
247 print ("Playing next song in %s s" % length) | |
248 reactor.callLater(length, self.playNext, room_jid, profile) | |
249 | |
208 | 250 |
209 def radiocol_game_cmd(self, mess_elt, profile): | 251 def radiocol_game_cmd(self, mess_elt, profile): |
252 #FIXME: we should check sender (is it referee ?) here before accepting commands | |
210 from_jid = jid.JID(mess_elt['from']) | 253 from_jid = jid.JID(mess_elt['from']) |
211 room_jid = jid.JID(from_jid.userhost()) | 254 room_jid = jid.JID(from_jid.userhost()) |
212 radio_elt = mess_elt.firstChildElement() | 255 radio_elt = mess_elt.firstChildElement() |
213 radio_data = self.radios[room_jid.userhost()] | 256 radio_data = self.radios[room_jid.userhost()] |
214 occupants_data = radio_data['occupants_data'] | 257 occupants_data = radio_data['occupants_data'] |
258 queue = radio_data['queue'] | |
215 | 259 |
216 for elt in radio_elt.elements(): | 260 for elt in radio_elt.elements(): |
217 | 261 |
218 if elt.name == 'started': #new game created | 262 if elt.name == 'started': #new game created |
219 self.host.bridge.radiocolStarted(room_jid.userhost(), from_jid.full(), profile) | 263 self.host.bridge.radiocolStarted(room_jid.userhost(), from_jid.full(), profile) |
220 elif elt.name == 'preload': #a song is in queue and must be preloaded | 264 elif elt.name == 'preload': #a song is in queue and must be preloaded |
221 self.host.bridge.radiocolPreload(room_jid.userhost(), elt['filename'], elt['title'], elt['artist'], elt['album'], profile) | 265 self.host.bridge.radiocolPreload(room_jid.userhost(), elt['filename'], elt['title'], elt['artist'], elt['album'], profile) |
266 elif elt.name == 'play': | |
267 self.host.bridge.radiocolPlay(room_jid.userhost(), elt['filename'], profile) | |
222 elif elt.name == 'song_rejected': #a song has been refused | 268 elif elt.name == 'song_rejected': #a song has been refused |
223 import pdb | 269 self.host.bridge.radiocolSongRejected(jid.JID(referee).userhost(), elt['reason'], profile) |
224 pdb.set_trace() | 270 elif elt.name == 'no_upload': |
225 elif elt.name == 'song_added': #a song has been refused | 271 self.host.bridge.radiocolNoUpload(room_jid.userhost(), profile) |
226 #FIXME: we are KISS for the PoC: every song is added. Need to manage some sort of rules to allow peoples to send songs | 272 elif elt.name == 'upload_ok': |
273 self.host.bridge.radiocolUploadOk(room_jid.userhost(), profile) | |
274 elif elt.name == 'song_added': #a song has been added | |
275 #FIXME: we are KISS for the proof of concept: every song is added, to a limit of 3 in queue. | |
276 # Need to manage some sort of rules to allow peoples to send songs | |
277 | |
278 if len(queue) >= QUEUE_LIMIT: | |
279 #there are already too many songs in queue, we reject this one | |
280 mess = self.createRadiocolElt(room_jid) | |
281 reject_elt = mess.firstChildElement().addElement(('','song_rejected')) | |
282 reject_elt['sender'] = from_jid.resource | |
283 reject_elt['reason'] = "Too many songs in queue" | |
284 #FIXME: add an error code | |
285 self.host.profiles[profile].xmlstream.send(mess) | |
286 return | |
287 | |
288 #The song is accepted and added in queue | |
289 queue.append((elt['filename'], float(elt['length']))) | |
290 | |
291 if len(queue) >= QUEUE_LIMIT: | |
292 #We are at the limit, we refuse new upload until next play | |
293 mess = self.createRadiocolElt(room_jid) | |
294 no_upload_elt = mess.firstChildElement().addElement(('','no_upload')) | |
295 #FIXME: add an error code | |
296 self.host.profiles[profile].xmlstream.send(mess) | |
297 radio_data['upload'] = False | |
298 | |
299 | |
227 mess = self.createRadiocolElt(room_jid) | 300 mess = self.createRadiocolElt(room_jid) |
228 preload_elt = mess.firstChildElement().addElement(('','preload')) | 301 preload_elt = self.__create_preload_elt(from_jid.resource, |
229 preload_elt['sender'] = from_jid.resource | 302 elt['filename'], |
230 preload_elt['filename'] = elt['filename'] #XXX: the frontend should know the temporary directory where file is put | 303 elt['title'], |
231 preload_elt['title'] = elt['title'] | 304 elt['artist'], |
232 preload_elt['artist'] = elt['artist'] | 305 elt['album']) |
233 preload_elt['album'] = elt['album'] | 306 mess.firstChildElement().addChild(preload_elt) |
234 preload_elt['length'] = elt['length'] | |
235 self.host.profiles[profile].xmlstream.send(mess) | 307 self.host.profiles[profile].xmlstream.send(mess) |
308 if not radio_data['playing'] and len(queue) == 2: | |
309 #we have not started playing yet, and we have 2 songs in queue | |
310 #we can now start the party :) | |
311 radio_data['playing'] = True | |
312 self.playNext(room_jid, profile) | |
236 else: | 313 else: |
237 error (_('Unmanaged game element: %s') % elt.name) | 314 error (_('Unmanaged game element: %s') % elt.name) |
238 | 315 |
239 def getHandler(self, profile): | 316 def getHandler(self, profile): |
240 return RadiocolHandler(self) | 317 return RadiocolHandler(self) |