From: pin Date: Thu, 22 Apr 2010 15:30:47 +0000 (+0000) Subject: premier jet sur le replay d'une chanson à partir d'un fichier de log. X-Git-Url: https://scm.cri.mines-paristech.fr/git/minwii.git/commitdiff_plain/f6e0db47250bd3666e1f46f22ed8153d77b46f2e?ds=sidebyside;hp=1146c6cc44b9dfde050dd218f343811661796ecc premier jet sur le replay d'une chanson à partir d'un fichier de log. git-svn-id: https://svn.cri.ensmp.fr/svn/minwii/trunk@160 fe552daf-6dbe-4428-90eb-1537e0879342 --- diff --git a/src/app/events.py b/src/app/events.py index eee6445..6b90d92 100755 --- a/src/app/events.py +++ b/src/app/events.py @@ -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()) diff --git a/src/app/log.py b/src/app/log.py index 725abac..e30daa9 100755 --- a/src/app/log.py +++ b/src/app/log.py @@ -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 index 0000000..502b332 --- /dev/null +++ b/src/app/logfilereader.py @@ -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 diff --git a/src/app/start.py b/src/app/start.py index 3f5f247..dd0b0d5 100755 --- a/src/app/start.py +++ b/src/app/start.py @@ -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 index 0000000..d49d8ac --- /dev/null +++ b/src/app/startlogreader.py @@ -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() diff --git a/src/app/widgets/playingscreen.py b/src/app/widgets/playingscreen.py index 736dd06..67039e7 100755 --- a/src/app/widgets/playingscreen.py +++ b/src/app/widgets/playingscreen.py @@ -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