Mercurial > libervia-backend
diff src/plugins/plugin_misc_radiocol.py @ 746:539f278bc265
plugin room_games, radiocol: send the current queue to new players
author | souliane <souliane@mailoo.org> |
---|---|
date | Thu, 28 Nov 2013 19:23:59 +0100 |
parents | 074970227bc0 |
children | d0e809014ea2 |
line wrap: on
line diff
--- a/src/plugins/plugin_misc_radiocol.py Tue Dec 10 09:02:20 2013 +0100 +++ b/src/plugins/plugin_misc_radiocol.py Thu Nov 28 19:23:59 2013 +0100 @@ -23,6 +23,8 @@ from twisted.words.protocols.jabber import jid import os.path +import copy +import time from os import unlink from mutagen.oggvorbis import OggVorbis, OggVorbisHeaderError @@ -41,6 +43,10 @@ "description": _("""Implementation of radio collective""") } + +# Number of songs needed in the queue before we start playing +QUEUE_TO_START = 2 +# Maximum number of songs in the queue (the song being currently played doesn't count) QUEUE_LIMIT = 2 @@ -61,20 +67,20 @@ host.bridge.addMethod("radiocolCreate", ".plugin", in_sign='sass', out_sign='', method=self.createGame) host.bridge.addMethod("radiocolSongAdded", ".plugin", in_sign='sss', out_sign='', method=self.radiocolSongAdded) host.bridge.addSignal("radiocolPlayers", ".plugin", signature='ssass') # room_jid, referee, players, profile - host.bridge.addSignal("radiocolStarted", ".plugin", signature='ssass') # room_jid, referee, players, profile + host.bridge.addSignal("radiocolStarted", ".plugin", signature='ssasais') # room_jid, referee, players, [QUEUE_TO_START, QUEUE_LIMIT], profile host.bridge.addSignal("radiocolSongRejected", ".plugin", signature='sss') # room_jid, reason, profile - host.bridge.addSignal("radiocolPreload", ".plugin", signature='ssssss') # room_jid, filename, title, artist, album, profile + host.bridge.addSignal("radiocolPreload", ".plugin", signature='sssssss') # room_jid, timestamp, filename, title, artist, album, profile host.bridge.addSignal("radiocolPlay", ".plugin", signature='sss') # room_jid, filename, profile host.bridge.addSignal("radiocolNoUpload", ".plugin", signature='ss') # room_jid, profile host.bridge.addSignal("radiocolUploadOk", ".plugin", signature='ss') # room_jid, profile - def __create_preload_elt(self, sender, filename, title, artist, album): - preload_elt = domish.Element((None, 'preload')) + def __create_preload_elt(self, sender, song_added_elt): + preload_elt = copy.deepcopy(song_added_elt) + preload_elt.name = 'preload' preload_elt['sender'] = sender - preload_elt['filename'] = filename # XXX: the frontend should know the temporary directory where file is put - preload_elt['title'] = title - preload_elt['artist'] = artist - preload_elt['album'] = album + preload_elt['timestamp'] = str(time.time()) + # attributes filename, title, artist, album, length have been copied + # XXX: the frontend should know the temporary directory where file is put return preload_elt def radiocolSongAdded(self, referee, song_path, profile): @@ -94,7 +100,7 @@ song = OggVorbis(song_path) except OggVorbisHeaderError: #this file is not ogg vorbis, we reject it - unlink(song_path) # FIXME: same host trick (see note above) + self.deleteFile(song_path) # FIXME: same host trick (see note above) self.host.bridge.radiocolSongRejected(jid.JID(referee).userhost(), "Uploaded file is not Ogg Vorbis song, only Ogg Vorbis songs are acceptable", profile) """mess = self.createGameElt(jid.JID(referee)) @@ -116,20 +122,25 @@ radio_data['to_delete'][attrs['filename']] = song_path # FIXME: works only because of the same host trick, see the note under the docstring def playNext(self, room_jid, profile): - """"Play next sont in queue if exists, and put a timer + """"Play next song in queue if exists, and put a timer which trigger after the song has been played to play next one""" - #TODO: need to check that there are still peoples in the room - # and clean the datas/stop the playlist if it's not the case #TODO: songs need to be erased once played or found invalids # ==> unlink done the Q&D way with the same host trick (see above) radio_data = self.games[room_jid.userhost()] + if len(radio_data['players']) == 0: + debug(_('No more participants in the radiocol: cleaning data')) + radio_data['queue'] = [] + for filename in radio_data['to_delete']: + self.deleteFile(radio_data, filename) + radio_data['to_delete'] = {} queue = radio_data['queue'] if not queue: #nothing left to play, we need to wait for uploads radio_data['playing'] = False return - filename, length = queue.pop(0) + song = queue.pop(0) + filename, length = song['filename'], float(song['length']) self.send(room_jid, ('', 'play'), {'filename': filename}, profile=profile) if not radio_data['upload'] and len(queue) < QUEUE_LIMIT: @@ -138,17 +149,23 @@ radio_data['upload'] = True reactor.callLater(length, self.playNext, room_jid, profile) + #we wait more than the song length to delete the file, to manage poorly reactive networks/clients + reactor.callLater(length + 90, self.deleteFile, radio_data, filename) # FIXME: same host trick (see above) + + def deleteFile(self, radio_data, filename): try: file_to_delete = radio_data['to_delete'][filename] except KeyError: error(_("INTERNAL ERROR: can't find full path of the song to delete")) - return - - #we wait more than the song length to delete the file, to manage poorly reactive networks/clients - reactor.callLater(length + 90, unlink, file_to_delete) # FIXME: same host trick (see above) + return False + try: + unlink(file_to_delete) + except OSError: + error(_("INTERNAL ERROR: can't find %s on the file system" % file_to_delete)) + return False + return True def room_game_cmd(self, mess_elt, profile): - #FIXME: we should check sender (is it referee ?) here before accepting commands from_jid = jid.JID(mess_elt['from']) room_jid = jid.JID(from_jid.userhost()) radio_elt = mess_elt.firstChildElement() @@ -156,16 +173,20 @@ if 'queue' in radio_data: queue = radio_data['queue'] + from_referee = self.isReferee(room_jid.userhost(), from_jid.resource) + to_referee = self.isReferee(room_jid.userhost(), jid.JID(mess_elt['to']).user) for elt in radio_elt.elements(): + if not from_referee and not (to_referee and elt.name == 'song_added'): + continue # sender must be referee, expect when a song is submitted if elt.name == 'started' or elt.name == 'players': # new game created players = [] for player in elt.elements(): players.append(unicode(player)) signal = self.host.bridge.radiocolStarted if elt.name == 'started' else self.host.bridge.radiocolPlayers - signal(room_jid.userhost(), from_jid.full(), players, profile) + signal(room_jid.userhost(), from_jid.full(), players, [QUEUE_TO_START, QUEUE_LIMIT], profile) elif elt.name == 'preload': # a song is in queue and must be preloaded - self.host.bridge.radiocolPreload(room_jid.userhost(), elt['filename'], elt['title'], elt['artist'], elt['album'], profile) + self.host.bridge.radiocolPreload(room_jid.userhost(), elt['timestamp'], elt['filename'], elt['title'], elt['artist'], elt['album'], profile) elif elt.name == 'play': self.host.bridge.radiocolPlay(room_jid.userhost(), elt['filename'], profile) elif elt.name == 'song_rejected': # a song has been refused @@ -180,32 +201,30 @@ if len(queue) >= QUEUE_LIMIT: #there are already too many songs in queue, we reject this one - attrs = {'sender': from_jid.resource, - 'reason': "Too many songs in queue" - } #FIXME: add an error code - self.send(room_jid, ('', 'song_rejected'), attrs, profile=profile) + self.send(from_jid, ('', 'song_rejected'), {'reason': "Too many songs in queue"}, profile=profile) return #The song is accepted and added in queue - queue.append((elt['filename'], float(elt['length']))) + preload_elt = self.__create_preload_elt(from_jid.resource, elt) + queue.append(preload_elt) if len(queue) >= QUEUE_LIMIT: #We are at the limit, we refuse new upload until next play - #FIXME: add an error code self.send(room_jid, ('', 'no_upload'), profile=profile) radio_data['upload'] = False - preload_elt = self.__create_preload_elt(from_jid.resource, - elt['filename'], - elt['title'], - elt['artist'], - elt['album']) self.send(room_jid, preload_elt, profile=profile) - if not radio_data['playing'] and len(queue) == 2: - #we have not started playing yet, and we have 2 songs in queue - #we can now start the party :) + if not radio_data['playing'] and len(queue) == QUEUE_TO_START: + # We have not started playing yet, and we have QUEUE_TO_START + # songs in queue. We can now start the party :) radio_data['playing'] = True self.playNext(room_jid, profile) else: error(_('Unmanaged game element: %s') % elt.name) + + def getSyncData(self, room_jid_s): + data = self.games[room_jid_s]['queue'] + if len(data) == QUEUE_LIMIT: + data.append(domish.Element((None, 'no_upload'))) + return data