X-Git-Url: https://scm.cri.ensmp.fr/git/minwii.git/blobdiff_plain/d2d0e07ee1695d69a6954133c7997974b55c62c8..46f3ffd7fdde386f41020171b5733e55a8e64a85:/src/app/logfilereader.py diff --git a/src/app/logfilereader.py b/src/app/logfilereader.py deleted file mode 100755 index f5f5d54..0000000 --- a/src/app/logfilereader.py +++ /dev/null @@ -1,212 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Module de lecture des fichiers de log minwii - -$Id$ -$URL$ -""" - -from widgets.playingscreen import PlayingScreenBase -from eventutils import EventDispatcher -from events import eventCodes -from synth import Synth -from musicxml import musicXml2Song -import pygame - -SUPPORTED_FILE_HEADER = 'ENV winwii log format version : 1.0' - -class LogFileReader(object) : - """ - classe utilitaire pour l'accès aux données d'un fichier de log MinWii. - """ - - def __init__(self, logfile) : - """ logfile : chemin d'accès au fichier de log MinWii. - le format supporté est actuellement la version 1.0 uniquement. - """ - if isinstance(logfile, str) : - self.logfile = open(logfile, 'r') - else : - self.logfile = logfile - - firstline = self.next() - assert firstline == SUPPORTED_FILE_HEADER - - - def getSongFile(self) : - "retourne le chemin d'accès au fichier musicxml de la chanson" - f = self.logfile - pos = f.tell() - - f.seek(0) - for l in self : - if l.startswith('APP chanson :') : - break - songfile = l.split(':', 1)[1].strip() - f.seek(pos) - return songfile - - def getSoundFontFile(self) : - "retourne le chemin d'accès au fichier de la soundfont (*.sf2)" - f = self.logfile - pos = f.tell() - f.seek(0) - for l in self : - if l.startswith('ENV soundfont :') : - break - soundFontFile = l.split(':', 1)[1].strip() - f.seek(pos) - return soundFontFile - - def getBank(self) : - "retourne le paramètre bank du synthétiseur (entier)" - f = self.logfile - pos = f.tell() - f.seek(0) - for l in self : - if l.startswith('APP bank :') : - break - f.seek(pos) - bank = l.split(':', 1)[1].strip() - return int(bank) - - def getPreset(self) : - "retourne le paramètre preset du synthétiseur (entier)" - f = self.logfile - pos = f.tell() - f.seek(0) - for l in self : - if l.startswith('APP preset :') : - break - f.seek(pos) - preset = l.split(':', 1)[1].strip() - return int(preset) - - def getScreenResolution(self) : - "retourne la résolution écran (tuple de deux entiers)" - f = self.logfile - pos = f.tell() - f.seek(0) - for l in self : - if l.startswith('ENV résolution écran :') : - break - screenResolution = eval(l.split(':', 1)[1].strip()) - f.seek(pos) - return screenResolution - - def getFirstEventTicks(self) : - "retourne le timecode du premier événement (entier)" - f = self.logfile - pos = f.tell() - f.seek(0) - for l in self : - if l.startswith('EVT ') : - break - firstTicks = int(l.split(None, 2)[1]) - f.seek(pos) - return firstTicks - - def __del__(self) : - self.logfile.close() - - def __iter__(self) : - return self - - def next(self) : - line = self.logfile.next().strip() - return line - - def getEventsIterator(self) : - """ Retourne un itérateur sur les événements. - Chaque itération retourne un tuple de 3 éléments : - (timecode, nom_événement, données) avec le typage : - (entier, chaîne, chaîne) - """ - self.logfile.seek(0) - while True : - try : - l = self.next() - except StopIteration : - break - - if not l.startswith('EVT ') : - continue - try : - ticks, eventName, message = l.split(None, 3)[1:] - ticks = int(ticks) - yield ticks, eventName, message - except ValueError : - ticks, eventName = l.split(None, 3)[1:] - ticks = int(ticks) - yield ticks, eventName, '' - - -class LogFilePlayer(PlayingScreenBase) : - """ - ré-exécution d'une chanson sur la base de son fichier de log. - """ - - def __init__(self, logfile) : - lfr = self.lfr = LogFileReader(logfile) - songFile = lfr.getSongFile() - soundFontFile = lfr.getSoundFontFile() - sfPath = lfr.getSoundFontFile() - bank = lfr.getBank() - preset = lfr.getPreset() - synth = Synth(sfPath=sfPath) - synth.program_select(0, bank, preset) - self.song = musicXml2Song(songFile) - screenResolution = lfr.getScreenResolution() - - pygame.display.set_mode(screenResolution) - - super(LogFilePlayer, self).__init__(synth, self.song.distinctNotes) - - def run(self): - self._running = True - clock = pygame.time.Clock() - pygame.display.flip() - pygame.mouse.set_visible(False) - - previousTicks = self.lfr.getFirstEventTicks() - eIter = self.lfr.getEventsIterator() - - for ticks, eventName, message in eIter : - t0 = pygame.time.get_ticks() - if eventName == 'COLSTATECHANGE' : - parts = message.split(None, 4) - if len(parts) == 4 : - parts.append('') - index, state, midi, name, syllabus = parts - index = int(index) - midi = int(midi) - state = state == 'True' - col = self.columns[midi] - col.update(state, syllabus=syllabus.decode('utf-8')) - - elif eventName == 'NOTEON': - chan, key, vel = [int(v) for v in message.split(None, 2)] - self.synth.noteon(chan, key, vel) - - elif eventName == 'NOTEOFF': - chan, key = [int(v) for v in message.split(None, 1)] - self.synth.noteoff(chan, key) - - elif eventName.startswith('COL') : - pos = [int(n) for n in message.split(None, 4)[-1].strip('()').split(',')] - self.cursor.setPosition(pos) - - - pygame.event.clear() - - dirty = self.draw(pygame.display.get_surface()) - pygame.display.update(dirty) - execTime = pygame.time.get_ticks() - t0 - - delay = ticks - previousTicks - execTime - if delay > 0 : - pygame.time.wait(delay) - - previousTicks = ticks - - \ No newline at end of file