Bugfixes en tout genre de la version 2.0.0.
[minwii.git] / src / minwii / app.py
1 # -*- coding: utf-8 -*-
2 """
3 l'application winwii
4
5 $Id$
6 $URL$
7 """
8
9 import pygame
10 from pgu.gui import Theme
11 from pgu.gui import Desktop
12 from pgu.gui import QUIT
13 from minwii.widgets.launch import LaunchScreen
14 from minwii.widgets.home import Home
15 from minwii.widgets.playingscreen import SongPlayingScreen, PlayingScreen
16 from minwii.widgets.instrumentselector import InstrumentSelector
17 from minwii.synth import Synth
18 from minwii.eventutils import EventDispatcher
19 from minwii.musicxml import musicXml2Song
20 from minwii.config import SONG_FILE_PATH
21 from minwii.config import SCREEN_RESOLUTION
22 from minwii.globals import PLAYING_MODES_DICT
23 from minwii.log import console, LOG_FORMAT_VERSION, envLogger
24 import os.path
25
26 wiiuse = None
27 pygame_wiimouse = None
28
29 SCREEN_HOME = 0
30 SCREEN_INSTRUMENTS = 1
31 SCREEN_PLAY = 2
32
33
34
35 class MinWii(object):
36
37 def __init__(self, wiimoteSupport=True, fullscreen=False) :
38 envLogger.info('winwii log format version : %s', LOG_FORMAT_VERSION)
39 self.wiimoteSupport = wiimoteSupport
40 self.fullscreen = fullscreen
41 LaunchScreen()
42 themedir = __file__.split(os.path.sep)[:-1] + ['widgets', 'data', 'minwii_theme']
43 themedir = os.path.sep.join(themedir)
44 theme = Theme(themedir)
45 self.app = Desktop(theme=theme)
46 self.synth = Synth()
47 self.screenResolution = SCREEN_RESOLUTION
48 envLogger.info('résolution écran : %s', self.screenResolution)
49 self.nwiimotes = 0
50 self.initWiimotes()
51 self.firstSong = True
52 self.screen = SCREEN_HOME
53 self.playingScreen = None
54
55 def initWiimotes(self) :
56 if self.wiimoteSupport :
57 global wiiuse
58 from pywiiuse import PyWiiUse as wiiuse
59 global pygame_wiimouse
60 from pywiiuse import pygame_wiimouse
61 from minwii.config import IR_POSITION
62 pygame_wiimouse.init(5, 5, self.screenResolution, IR_POSITION) # look for 5, wait 5 seconds
63 self.nwiimotes = nwiimotes = pygame_wiimouse.get_count()
64 console.debug('wiimotes found : %d', nwiimotes)
65 self.WT = WT = pygame_wiimouse.WT
66 WT.setEventCallBack(self._wiimotesEventCallBack)
67 WT.pause()
68 else :
69 self.WT = _WTFacade()
70
71 def _wiimotesEventCallBack(self, wt, id, wmp) :
72 if self.screen == SCREEN_PLAY :
73 pygame_wiimouse._default_event_cb(wt, id, wmp)
74
75 wm = wmp[0]
76 if id == self.nwiimotes - 1 :
77 # le bouton Home de la télécommande permet de sortir
78 # (envoi d'un événement clavier « q »)
79 if wiiuse.is_just_pressed(wm, wiiuse.button['Home']) :
80 event = pygame.event.Event(pygame.KEYDOWN,
81 key = pygame.K_q,
82 unicode = u'q')
83 pygame.event.post(event)
84 elif wiiuse.is_just_pressed(wm, wiiuse.button['+']) :
85 self.synth.inc_gain()
86 elif wiiuse.is_just_pressed(wm, wiiuse.button['-']) :
87 self.synth.dec_gain()
88 elif wiiuse.is_just_pressed(wm, wiiuse.button['1']) and self.playingScreen :
89 self.playingScreen.tempoTrimUp()
90 elif wiiuse.is_just_pressed(wm, wiiuse.button['2']) and self.playingScreen :
91 self.playingScreen.tempoTrimDown()
92
93 elif self.screen in (SCREEN_HOME, SCREEN_INSTRUMENTS) :
94 pygame_wiimouse._full_mouse_event_cb(wt, id, wmp)
95
96 def run(self) :
97 "séquençage de l'affichage des écrans"
98 displayFlags = 0
99 if self.fullscreen :
100 displayFlags = displayFlags | pygame.FULLSCREEN
101 pygame.display.set_mode(self.screenResolution, displayFlags)
102 pygame.display.set_caption('MINWii')
103 WT = self.WT
104
105 songFile, playMode, displayNotes, wiimoteIndex = '', 'NORMAL', True, 0
106
107 while True :
108 WT.resume()
109 WT.selectWiimote(self.nwiimotes - 1) # la télécommande est la souris
110 self.screen = SCREEN_HOME
111 exit, songFile, playMode, displayNotes, wiimoteIndex = \
112 self.selectSongAndOptions(songFile, playMode, displayNotes, wiimoteIndex)
113 if exit :
114 WT.quit()
115 break
116
117
118 self.screen = SCREEN_INSTRUMENTS
119 instrumentDescription = self.selectInstrument()
120 if not instrumentDescription :
121 continue
122
123 self.screen = SCREEN_PLAY
124 WT.selectWiimote(wiimoteIndex)
125 self.runPlayingScreen(songFile, playMode, displayNotes, instrumentDescription)
126 WT.pause()
127
128
129 def selectSongAndOptions(self, songFile, playMode, displayNotes, wiimoteIndex) :
130 """ lance l'écran de paramétrage et retourne un tuple comportant :
131 - drapeau de sortie de l'application (booléen)
132 - chemin du fichier de la chanson
133 - mode (entier)
134 - affichage des notes (booléen)
135 - wiimote sélectionnée (entier)
136 """
137 home = Home(songPath=SONG_FILE_PATH,
138 songFile=songFile,
139 playMode=playMode,
140 displayNotes=displayNotes,
141 wiimoteIndex=wiimoteIndex,
142 nwiimotes=self.nwiimotes)
143 app = self.app
144 home.connect(QUIT, app.quit)
145 app.run(home)
146 app.close(home)
147
148 #logging
149 if home.exitApp :
150 console.debug("sortie de l'application")
151 else :
152 actual_wiimotes = self.WT.get_count()
153 if self.firstSong :
154 self.firstSong = False
155 else :
156 envLogger.info('NEW_LOG_FILE')
157 console.info('chanson : %s', home.songFile)
158 console.info('mode : %s', home.modeSelect.value)
159 if actual_wiimotes is None :
160 console.info('HID : souris')
161 elif actual_wiimotes == 0 :
162 console.info('HID : souris (pas de wiimote trouvée)')
163 else :
164 console.info('HID : wiimote %d', home.selectedWiimote.value + 1)
165 #---
166
167 return (home.exitApp,
168 home.songFile,
169 home.selectedPlayMode,
170 home.displayNotes,
171 home.selectedWiimoteIndex)
172
173 def selectInstrument(self) :
174 """ lance l'écran de sélection de l'instrument et retourne
175 un dictionnaire comportant la description de l'instrument
176 """
177 selector = InstrumentSelector()
178 selector.run()
179 selector.stop()
180 pygame.event.clear()
181 EventDispatcher.reset()
182 instru = selector.selectedInstrument
183 if instru :
184 console.info('instrument : %s', instru['name'])
185 console.info('preset : %d', instru['preset'])
186 console.info('bank : %d', instru['bank'])
187 console.info('ajustement octave : %d', instru['octave'])
188 return instru
189
190 def runPlayingScreen(self, songFile, playMode, displayNotes, instrumentDescription) :
191 """ Lance l'écran de jeu principal avec la chanson 'songFile' dans le mode 'playMode'
192 avec l'instrument midi 'instrumentDescription'.
193 """
194 playMode = PLAYING_MODES_DICT[playMode]
195 bank, preset = instrumentDescription['bank'], instrumentDescription['preset']
196 octave = instrumentDescription['octave']
197 self.synth.adjust_octave(0, octave)
198 self.synth.program_select(0, bank, preset)
199 if playMode == PLAYING_MODES_DICT['IMPRO'] :
200 playingScreen = PlayingScreen(self.synth, displayNotes=displayNotes)
201 else :
202 song = musicXml2Song(songFile)
203 self.playingScreen = playingScreen = SongPlayingScreen(self.synth, song, mode=playMode, displayNotes=displayNotes)
204 playingScreen.run()
205 pygame.event.clear()
206 EventDispatcher.reset()
207 self.playingScreen = None
208
209
210 class _WTFacade :
211 """ Classe utilitaire pour singer l'api
212 de pygame_wiimouse en cas d'abscence de wiimote.
213 """
214 selectWimoteIndex = 0
215 def pause(self):
216 pass
217 def resume(self):
218 pass
219 def selectWiimote(self, i):
220 pass
221 def get_count(self) :
222 return None