comparison src/plugins/plugin_misc_radiocol.py @ 577:593331663b80

plugin radiocol: songs are deleted once played (Q&D need to be reworked once file are properly transfered to server)
author Goffi <goffi@goffi.org>
date Wed, 09 Jan 2013 21:41:40 +0100
parents ca13633d3b6b
children 952322b1d490
comparison
equal deleted inserted replaced
576:a60dd719e048 577:593331663b80
19 along with this program. If not, see <http://www.gnu.org/licenses/>. 19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 """ 20 """
21 21
22 from logging import debug, info, warning, error 22 from logging import debug, info, warning, error
23 from twisted.words.xish import domish 23 from twisted.words.xish import domish
24 from twisted.internet import protocol, defer, threads, reactor 24 from twisted.internet import reactor
25 from twisted.words.protocols.jabber import client, jid, xmlstream 25 from twisted.words.protocols.jabber import jid
26 from twisted.words.protocols.jabber import error as jab_error 26
27 from twisted.words.protocols.jabber.xmlstream import IQ 27 from wokkel import disco, iwokkel
28 import random
29 28
30 from zope.interface import implements 29 from zope.interface import implements
31 30
32 from wokkel import disco, iwokkel, data_form
33 from sat.tools.xml_tools import dataForm2xml
34 from sat.tools.games import TarotCard
35
36 from time import time
37 import os.path 31 import os.path
32 from os import unlink
38 from mutagen.oggvorbis import OggVorbis, OggVorbisHeaderError 33 from mutagen.oggvorbis import OggVorbis, OggVorbisHeaderError
39 34
40 try: 35 try:
41 from twisted.words.protocols.xmlstream import XMPPHandler 36 from twisted.words.protocols.xmlstream import XMPPHandler
42 except ImportError: 37 except ImportError:
170 room_nick = self.host.plugins["XEP-0045"].getRoomNick(room_jid.userhost(), profile) 165 room_nick = self.host.plugins["XEP-0045"].getRoomNick(room_jid.userhost(), profile)
171 if not room_nick: 166 if not room_nick:
172 error ('Internal error') 167 error ('Internal error')
173 return 168 return
174 referee = room_jid.userhost() + '/' + room_nick 169 referee = room_jid.userhost() + '/' + room_nick
175 status = {} 170 self.radios[room_jid.userhost()] = {'referee':referee, 'queue':[], 'upload':True, 'playing': False, 'occupants_data':{}, 'to_delete':{}}
176 occupants_data = {}
177 self.radios[room_jid.userhost()] = {'referee':referee, 'queue':[], 'upload':True, 'playing': False, 'occupants_data':occupants_data}
178 mess = self.createRadiocolElt(jid.JID(room_jid.userhost())) 171 mess = self.createRadiocolElt(jid.JID(room_jid.userhost()))
179 mess.firstChildElement().addChild(self.__create_started_elt()) 172 mess.firstChildElement().addChild(self.__create_started_elt())
180 self.host.profiles[profile].xmlstream.send(mess) 173 self.host.profiles[profile].xmlstream.send(mess)
181 174
182 def radiocolSongAdded(self, referee, song_path, profile): 175 def radiocolSongAdded(self, referee, song_path, profile):
194 return 187 return
195 try: 188 try:
196 song = OggVorbis(song_path) 189 song = OggVorbis(song_path)
197 except OggVorbisHeaderError: 190 except OggVorbisHeaderError:
198 #this file is not ogg vorbis, we reject it 191 #this file is not ogg vorbis, we reject it
192 unlink(song_path) # FIXME: same host trick (see note above)
199 self.host.bridge.radiocolSongRejected(jid.JID(referee).userhost(), \ 193 self.host.bridge.radiocolSongRejected(jid.JID(referee).userhost(), \
200 "Uploaded file is not Ogg Vorbis song, only Ogg Vorbis songs are acceptable", profile) 194 "Uploaded file is not Ogg Vorbis song, only Ogg Vorbis songs are acceptable", profile)
201 """mess = self.createRadiocolElt(jid.JID(referee)) 195 """mess = self.createRadiocolElt(jid.JID(referee))
202 reject_elt = mess.firstChildElement().addElement(('','song_rejected')) 196 reject_elt = mess.firstChildElement().addElement(('','song_rejected'))
203 reject_elt['sender'] = client.jid 197 reject_elt['sender'] = client.jid
209 artist = song.get("artist", ["Unknown"])[0] 203 artist = song.get("artist", ["Unknown"])[0]
210 album = song.get("album", ["Unknown"])[0] 204 album = song.get("album", ["Unknown"])[0]
211 length = song.info.length 205 length = song.info.length
212 mess = self.createRadiocolElt(jid.JID(referee)) 206 mess = self.createRadiocolElt(jid.JID(referee))
213 added_elt = mess.firstChildElement().addElement(('','song_added')) 207 added_elt = mess.firstChildElement().addElement(('','song_added'))
214 added_elt['filename'] = os.path.basename(song_path) 208 added_elt['filename'] = filename = os.path.basename(song_path)
215 added_elt['title'] = title 209 added_elt['title'] = title
216 added_elt['artist'] = artist 210 added_elt['artist'] = artist
217 added_elt['album'] = album 211 added_elt['album'] = album
218 added_elt['length'] = str(length) 212 added_elt['length'] = str(length)
219 self.host.profiles[profile].xmlstream.send(mess) 213 self.host.profiles[profile].xmlstream.send(mess)
220 return 214
215 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
221 217
222 def playNext(self, room_jid, profile): 218 def playNext(self, room_jid, profile):
223 """"Play next sont in queue if exists, and put a timer 219 """"Play next sont in queue if exists, and put a timer
224 which trigger after the song has been played to play next one""" 220 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 221 #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 222 # and clean the datas/stop the playlist if it's not the case
227 #TODO: songs need to be erased once played or found invalids 223 #TODO: songs need to be erased once played or found invalids
224 # ==> unlink done the Q&D way with the same host trick (see above)
228 radio_data = self.radios[room_jid.userhost()] 225 radio_data = self.radios[room_jid.userhost()]
229 queue = radio_data['queue'] 226 queue = radio_data['queue']
230 if not queue: 227 if not queue:
231 #nothing left to play, we need to wait for uploads 228 #nothing left to play, we need to wait for uploads
232 radio_data['playing'] = False 229 radio_data['playing'] = False
243 mess = self.createRadiocolElt(room_jid) 240 mess = self.createRadiocolElt(room_jid)
244 no_upload_elt = mess.firstChildElement().addElement(('','upload_ok')) 241 no_upload_elt = mess.firstChildElement().addElement(('','upload_ok'))
245 self.host.profiles[profile].xmlstream.send(mess) 242 self.host.profiles[profile].xmlstream.send(mess)
246 radio_data['upload'] = True 243 radio_data['upload'] = True
247 244
248 print ("Playing next song in %s s" % length)
249 reactor.callLater(length, self.playNext, room_jid, profile) 245 reactor.callLater(length, self.playNext, room_jid, profile)
246 try:
247 file_to_delete = radio_data['to_delete'][filename]
248 except KeyError:
249 error(_("INTERNAL ERROR: can't find full path of the song to delete"))
250 return
251
252 #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)
250 254
251 255
252 def radiocol_game_cmd(self, mess_elt, profile): 256 def radiocol_game_cmd(self, mess_elt, profile):
253 #FIXME: we should check sender (is it referee ?) here before accepting commands 257 #FIXME: we should check sender (is it referee ?) here before accepting commands
254 from_jid = jid.JID(mess_elt['from']) 258 from_jid = jid.JID(mess_elt['from'])
265 elif elt.name == 'preload': #a song is in queue and must be preloaded 269 elif elt.name == 'preload': #a song is in queue and must be preloaded
266 self.host.bridge.radiocolPreload(room_jid.userhost(), elt['filename'], elt['title'], elt['artist'], elt['album'], profile) 270 self.host.bridge.radiocolPreload(room_jid.userhost(), elt['filename'], elt['title'], elt['artist'], elt['album'], profile)
267 elif elt.name == 'play': 271 elif elt.name == 'play':
268 self.host.bridge.radiocolPlay(room_jid.userhost(), elt['filename'], profile) 272 self.host.bridge.radiocolPlay(room_jid.userhost(), elt['filename'], profile)
269 elif elt.name == 'song_rejected': #a song has been refused 273 elif elt.name == 'song_rejected': #a song has been refused
270 self.host.bridge.radiocolSongRejected(jid.JID(referee).userhost(), elt['reason'], profile) 274 self.host.bridge.radiocolSongRejected(room_jid.userhost(), elt['reason'], profile)
271 elif elt.name == 'no_upload': 275 elif elt.name == 'no_upload':
272 self.host.bridge.radiocolNoUpload(room_jid.userhost(), profile) 276 self.host.bridge.radiocolNoUpload(room_jid.userhost(), profile)
273 elif elt.name == 'upload_ok': 277 elif elt.name == 'upload_ok':
274 self.host.bridge.radiocolUploadOk(room_jid.userhost(), profile) 278 self.host.bridge.radiocolUploadOk(room_jid.userhost(), profile)
275 elif elt.name == 'song_added': #a song has been added 279 elif elt.name == 'song_added': #a song has been added