premier jet sur le replay d'une chanson à partir d'un fichier de log.
authorpin <pin@fe552daf-6dbe-4428-90eb-1537e0879342>
Thu, 22 Apr 2010 15:30:47 +0000 (15:30 +0000)
committerpin <pin@fe552daf-6dbe-4428-90eb-1537e0879342>
Thu, 22 Apr 2010 15:30:47 +0000 (15:30 +0000)
git-svn-id: https://svn.cri.ensmp.fr/svn/minwii/trunk@160 fe552daf-6dbe-4428-90eb-1537e0879342

src/app/events.py
src/app/log.py
src/app/logfilereader.py [new file with mode: 0755]
src/app/start.py
src/app/startlogreader.py [new file with mode: 0755]
src/app/widgets/playingscreen.py

index eee6445..6b90d92 100755 (executable)
@@ -41,3 +41,5 @@ pygame_events = [
 
 for name in pygame_events :
     eventNames[getattr(pygame, name)] = name
+
+eventCodes = dict([v, k] for k, v in eventNames.items())
index 725abac..e30daa9 100755 (executable)
@@ -26,9 +26,6 @@ logsdir = os.path.join(os.path.expanduser('~'), 'minwii_logs')
 if not os.path.exists(logsdir) :
     os.mkdir(logsdir)
 
-#logfile = os.path.join(logsdir, datetime.datetime.now().strftime('%Y-%m-%d-%H_%M_%S.log'))
-#logfile = open(logfile, 'w')
-
 
 class MinWiiStreamHandler(logging.StreamHandler) :
     logfile = None
diff --git a/src/app/logfilereader.py b/src/app/logfilereader.py
new file mode 100755 (executable)
index 0000000..502b332
--- /dev/null
@@ -0,0 +1,159 @@
+# -*- 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-alpha'
+
+class LogFileReader(object) :
+    
+    def __init__(self, logfile) :
+        if isinstance(logfile, str) :
+            self.logfile = open(logfile, 'r')
+        else :
+            self.logfile = logfile
+        
+        firstline = self.next()
+        assert firstline == SUPPORTED_FILE_HEADER
+        
+    
+    def getSongFile(self) :
+        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) :
+        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()
+        return soundFontFile
+
+    def getScreenResolution(self) :
+        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())
+        return screenResolution
+    
+    def getFirstEventTicks(self) :
+        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])
+        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) :
+        while True :
+            try :
+                l = self.next()
+            except StopIteration :
+                break
+            
+            if not l.startswith('EVT ') :
+                continue
+            try :
+                ticks, eventName, message = l.split(None, 3)[1:]
+                yield ticks, eventName, message
+            except ValueError :
+                ticks, eventName = l.split(None, 3)[1:]
+                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()
+       synth = Synth(sfPath=sfPath)
+       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 :
+            ticks = int(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'))
+                
+            pygame.event.clear() # à virer
+            #EventDispatcher.dispatchEvents()
+
+            dirty = self.draw(pygame.display.get_surface())
+            pygame.display.update(dirty)
+            execTime = clock.tick()
+            
+            delay = ticks - previousTicks - execTime
+            if delay > 0 :
+                pygame.time.wait(delay)
+            
+            previousTicks = ticks
+            #print ticks, eventName, message
+            
+        #while self._running :
+        #    EventDispatcher.dispatchEvents()
+        #    dirty = self.draw(pygame.display.get_surface())
+        #    pygame.display.update(dirty)
+        #    clock.tick()
+        
+    
\ No newline at end of file
index 3f5f247..dd0b0d5 100755 (executable)
@@ -12,18 +12,9 @@ $URL$
 def main(wiimoteSupport) :
     import pygame
     from minwii import MinWii
-    
     pygame.init()
-    #modeResolution = (1024,768)
-    #modeResolution = (600,480)
-    #pygame.display.set_mode(modeResolution, pygame.NOFRAME)#, pygame.FULLSCREEN)
     minwii = MinWii(wiimoteSupport=wiimoteSupport)
     minwii.run()
-    # from gui.PGUConfiguration import PGUConfiguration
-    # pygame.init()
-    # modeResolution = (1024,768)
-    # window = pygame.display.set_mode(modeResolution)#,pygame.FULLSCREEN)
-    # pgu = PGUConfiguration(window)
     pygame.quit()   
 
 if __name__ == "__main__" :
@@ -31,7 +22,7 @@ if __name__ == "__main__" :
     import sys
     from optparse import OptionParser
     
-    usage = "%prog instance_home products_conf_file [options]"
+    usage = "%prog [options]"
     op = OptionParser(usage)
     
     op.add_option("--no-wii", dest="wiimoteSupport"
diff --git a/src/app/startlogreader.py b/src/app/startlogreader.py
new file mode 100755 (executable)
index 0000000..d49d8ac
--- /dev/null
@@ -0,0 +1,42 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+lancement du lecteur de fichier de log minwii
+
+$Id$
+$URL$
+"""
+from os.path import realpath, sep
+import sys
+
+
+def main() :
+    from optparse import OptionParser
+    import pygame
+    from logfilereader import LogFilePlayer
+    
+    usage = "%prog logfile"
+    op = OptionParser(usage)
+    options, args = op.parse_args()
+    if len(args) != 1 :
+        op.error("incorrect number of arguments")
+    
+    
+    pygame.init()
+    lfp = LogFilePlayer(args[0])
+    lfp.run()
+    pygame.quit()   
+    
+    
+#    lr = LogFileReader(args[0])
+#    
+#    print lr.getSongFile()
+#        
+    
+
+if __name__ == "__main__" :
+    minwiipath = realpath(__file__).split(sep)
+    minwiipath = minwiipath[:-2]
+    minwiipath = sep.join(minwiipath)
+    sys.path.insert(1, minwiipath)
+    main()
index 736dd06..67039e7 100755 (executable)
@@ -23,14 +23,14 @@ from globals import BACKGROUND_LAYER
 from globals import CURSOR_LAYER
 from globals import PLAYING_MODES_DICT
 
-class _PlayingScreenBase(pygame.sprite.LayeredDirty, EventHandlerMixin) :
+class PlayingScreenBase(pygame.sprite.LayeredDirty, EventHandlerMixin) :
 
     def __init__(self, synth, distinctNotes=[]) :
         """
         distinctNotes : notes disctinctes présentes dans la chanson
         triées du plus grave au plus aigu.
         """
-        super(_PlayingScreenBase, self).__init__()
+        super(PlayingScreenBase, self).__init__()
         self.synth = synth
         self.distinctNotes = distinctNotes
         self.keyboardLength = 0
@@ -47,16 +47,10 @@ class _PlayingScreenBase(pygame.sprite.LayeredDirty, EventHandlerMixin) :
         """ création des espaces réservés pour
             afficher les colonnes.
         """
-        #ambitus = self.distinctNotes[-1].midi - self.distinctNotes[0].midi
-        #if ambitus <= 12 :
-        #    self.keyboardLength = 8
-        #else :
-        #    self.keyboardLength = 11
         self.keyboardLength = len(self.distinctNotes)
         
         screen = pygame.display.get_surface()
 
-        # taille de la zone d'affichage utile (bordure autour)
         self.dispWidth  = dispWidth = screen.get_width()
         self.dispHeight = dispHeight = screen.get_height()
         
@@ -94,7 +88,7 @@ class _PlayingScreenBase(pygame.sprite.LayeredDirty, EventHandlerMixin) :
             EventDispatcher.dispatchEvents()
             dirty = self.draw(pygame.display.get_surface())
             pygame.display.update(dirty)
-            clock.tick(FRAMERATE)
+            clock.tick()
     
     def stop(self) :
         self._running = False
@@ -153,7 +147,7 @@ class _PlayingScreenBase(pygame.sprite.LayeredDirty, EventHandlerMixin) :
         return pan
 
         
-class PlayingScreen(_PlayingScreenBase) :
+class PlayingScreen(PlayingScreenBase) :
     "fenêtre de jeu pour improvisation"
     
     scale = [55, 57, 59, 60, 62, 64, 65, 67, 69, 71, 72]
@@ -177,7 +171,7 @@ class PlayingScreen(_PlayingScreenBase) :
         self.synth.noteoff(0, tone.midi)
 
 
-class SongPlayingScreen(_PlayingScreenBase) :
+class SongPlayingScreen(PlayingScreenBase) :
     
     def __init__(self, synth, song, mode=PLAYING_MODES_DICT['EASY']) :
         super(SongPlayingScreen, self).__init__(synth, song.distinctNotes)
@@ -244,4 +238,5 @@ class SongPlayingScreen(_PlayingScreenBase) :
     def stop(self) :
         pygame.time.set_timer(events.NOTEEND, 0)
         super(SongPlayingScreen, self).stop()
-
+       
+       
\ No newline at end of file