X-Git-Url: https://scm.cri.ensmp.fr/git/minwii.git/blobdiff_plain/eec2dd4ea183465c2c95546402447303ee6320e4..14da21fe55fe951d06fdaa5900032fa0eabaea1f:/src/minwii/logfilereader.py diff --git a/src/minwii/logfilereader.py b/src/minwii/logfilereader.py index 29425f7..a5a2d35 100755 --- a/src/minwii/logfilereader.py +++ b/src/minwii/logfilereader.py @@ -6,120 +6,122 @@ $Id$ $URL$ """ +from types import StringTypes from widgets.playingscreen import PlayingScreenBase from eventutils import EventDispatcher from events import eventCodes from synth import Synth from musicxml import musicXml2Song import pygame +from backwardsfilereader import BackwardsReader SUPPORTED_FILE_HEADER = 'ENV winwii log format version : 1.0' +def inplaceread(m) : + def readinplace(self, *args, **kw) : + pos = self.logfile.tell() + self.logfile.seek(0) + ret = m(self, *args, **kw) + self.logfile.seek(pos) + return ret + return readinplace + class LogFileReader(object) : """ classe utilitaire pour l'accès aux données d'un fichier de log MinWii. """ - def __init__(self, logfile) : + def __init__(self, logfile, mode='r') : """ 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') + if isinstance(logfile, StringTypes) : + self.logfile = open(logfile, mode) else : self.logfile = logfile firstline = self.next() assert firstline == SUPPORTED_FILE_HEADER - + + @inplaceread 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 + @inplaceread 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 - + + @inplaceread 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) + @inplaceread 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) + @inplaceread 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 + @inplaceread def getMode(self) : "retourne le niveau de difficulté" - f = self.logfile - pos = f.tell() for l in self : if l.startswith('APP mode :') : break mode = l.split(':', 1)[1].strip() - f.geek(pos) return mode + @inplaceread 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 + @inplaceread + def getLastEventTicks(self) : + "retourne le timecode du dernier événement (entier)" + for l in self.getBackwardLineIterator() : + if l.startswith('EVT ') : + break + else : + return None + + lastTicks = int(l.split(None, 2)[1]) + return lastTicks + def __del__(self) : - self.logfile.close() + self.close() def __iter__(self) : return self @@ -151,6 +153,47 @@ class LogFileReader(object) : ticks, eventName = l.split(None, 3)[1:] ticks = int(ticks) yield ticks, eventName, '' + + def getBackwardLineIterator(self) : + br = BackwardsReader(self.logfile, BLKSIZE=128) + line = br.readline() + while line : + yield line.strip() + line = br.readline() + + @inplaceread + def getMetadata(self) : + metadata = {} + self.next() # skip identification line. + line = self.next() + while line.startswith('METADATA ') : + line = line.split(None, 1)[1] + name, value = [v.strip() for v in line.split(':', 1)] + metadata[name] = value + line = self.next() + return metadata + + def setMetadata(self, metadata) : + f = self.logfile + f.seek(0) + before = f.readline() + line = f.readline() + while line.startswith('METADATA ') : + line = f.readline() + after = line + f.read() + + lines = [] + for name, value in metadata : + lines.append('METADATA %s : %s' % (name, value.encode('utf-8'))) + metadata = '\n'.join(lines) + f.seek(0) + f.write(before) + f.write(metadata) + f.write(after) + + def close(self) : + self.logfile.close() + class LogFilePlayer(PlayingScreenBase) : @@ -222,5 +265,4 @@ class LogFilePlayer(PlayingScreenBase) : previousTicks = ticks self.stop() - \ No newline at end of file