Ajout de l'analyseur des logs.
[minwii.git] / src / minwii / logfilereader.py
index 29425f7..648cdee 100755 (executable)
@@ -12,9 +12,19 @@ from events import eventCodes
 from synth import Synth
 from musicxml import musicXml2Song
 import pygame
 from synth import Synth
 from musicxml import musicXml2Song
 import pygame
+from backwardsfilereader import BackwardsReader
 
 SUPPORTED_FILE_HEADER = 'ENV winwii log format version : 1.0'
 
 
 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.
 class LogFileReader(object) :
     """
     classe utilitaire pour l'accès aux données d'un fichier de log MinWii.
@@ -31,93 +41,82 @@ class LogFileReader(object) :
         
         firstline = self.next()
         assert firstline == SUPPORTED_FILE_HEADER
         
         firstline = self.next()
         assert firstline == SUPPORTED_FILE_HEADER
-        
     
     
+        
+    @inplaceread
     def getSongFile(self) :
         "retourne le chemin d'accès au fichier musicxml de la chanson"
     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()
         for l in self :
             if l.startswith('APP chanson :') :
                 break
         songfile = l.split(':', 1)[1].strip()
-        f.seek(pos)
         return songfile
     
         return songfile
     
+    @inplaceread
     def getSoundFontFile(self) :
         "retourne le chemin d'accès au fichier de la soundfont (*.sf2)"
     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()
         for l in self :
             if l.startswith('ENV soundfont :') :
                 break
         soundFontFile = l.split(':', 1)[1].strip()
-        f.seek(pos)
         return soundFontFile
         return soundFontFile
-
+    
+    @inplaceread
     def getBank(self) :
         "retourne le paramètre bank du synthétiseur (entier)"
     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
         for l in self :
             if l.startswith('APP bank :') :
                 break
-        f.seek(pos)
         bank = l.split(':', 1)[1].strip()
         return int(bank)
     
         bank = l.split(':', 1)[1].strip()
         return int(bank)
     
+    @inplaceread
     def getPreset(self) :
         "retourne le paramètre preset du synthétiseur (entier)"
     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
         for l in self :
             if l.startswith('APP preset :') :
                 break
-        f.seek(pos)
         preset = l.split(':', 1)[1].strip()
         return int(preset)
 
         preset = l.split(':', 1)[1].strip()
         return int(preset)
 
+    @inplaceread
     def getScreenResolution(self) :
         "retourne la résolution écran (tuple de deux entiers)"
     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())
         for l in self :
             if l.startswith('ENV résolution écran :') :
                 break
         screenResolution = eval(l.split(':', 1)[1].strip())
-        f.seek(pos)
         return screenResolution
     
         return screenResolution
     
+    @inplaceread
     def getMode(self) :
         "retourne le niveau de difficulté"
     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()
         for l in self :
             if l.startswith('APP mode :') :
                 break
             
         mode = l.split(':', 1)[1].strip()
-        f.geek(pos)
         return mode
     
         return mode
     
+    @inplaceread
     def getFirstEventTicks(self) :
         "retourne le timecode du premier événement (entier)"
     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])
         for l in self :
             if l.startswith('EVT ') :
                 break
         firstTicks = int(l.split(None, 2)[1])
-        f.seek(pos)
         return firstTicks
     
         return firstTicks
     
+    @inplaceread
+    def getLastEventTicks(self) :
+        "retourne le timecode du dernier événement (entier)"
+        for l in self.getBackwardLineIterator() :
+            if l.startswith('EVT ') :
+                break
+        
+        lastTicks = int(l.split(None, 2)[1])
+        return lastTicks
+    
     def __del__(self) :
         self.logfile.close()
     
     def __del__(self) :
         self.logfile.close()
     
@@ -151,6 +150,14 @@ class LogFileReader(object) :
                 ticks, eventName = l.split(None, 3)[1:]
                 ticks = int(ticks)
                 yield ticks, eventName, ''
                 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()
+        
                 
 
 class LogFilePlayer(PlayingScreenBase) :
                 
 
 class LogFilePlayer(PlayingScreenBase) :