Ajout d'une option pour afficher / masquer les noms de notes en bas du clavier.
[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 : break
114
115
116 self.screen = SCREEN_INSTRUMENTS
117 instrumentDescription = self.selectInstrument()
118 if not instrumentDescription :
119 continue
120
121 self.screen = SCREEN_PLAY
122 WT.selectWiimote(wiimoteIndex)
123 self.runPlayingScreen(songFile, playMode, displayNotes, instrumentDescription)
124 WT.pause()
125
126
127 def selectSongAndOptions(self, songFile, playMode, displayNotes, wiimoteIndex) :
128 """ lance l'écran de paramétrage et retourne un tuple comportant :
129 - drapeau de sortie de l'application (booléen)
130 - chemin du fichier de la chanson
131 - mode (entier)
132 - affichage des notes (booléen)
133 - wiimote sélectionnée (entier)
134 """
135 home = Home(songPath=SONG_FILE_PATH,
136 songFile=songFile,
137 playMode=playMode,
138 displayNotes=displayNotes,
139 wiimoteIndex=wiimoteIndex,
140 nwiimotes=self.nwiimotes)
141 app = self.app
142 home.connect(QUIT, app.quit)
143 app.run(home)
144 app.close(home)
145
146 #logging
147 if home.exitApp :
148 console.debug("sortie de l'application")
149 else :
150 actual_wiimotes = self.WT.get_count()
151 if self.firstSong :
152 self.firstSong = False
153 else :
154 envLogger.info('NEW_LOG_FILE')
155 console.info('chanson : %s', home.songFile)
156 console.info('mode : %s', home.modeSelect.value)
157 if actual_wiimotes is None :
158 console.info('HID : souris')
159 elif actual_wiimotes == 0 :
160 console.info('HID : souris (pas de wiimote trouvée)')
161 else :
162 console.info('HID : wiimote %d', home.selectedWiimote.value + 1)
163 #---
164
165 return (home.exitApp,
166 home.songFile,
167 home.selectedPlayMode,
168 home.displayNotes,
169 home.selectedWiimoteIndex)
170
171 def selectInstrument(self) :
172 """ lance l'écran de sélection de l'instrument et retourne
173 un dictionnaire comportant la description de l'instrument
174 """
175 selector = InstrumentSelector()
176 selector.run()
177 selector.stop()
178 pygame.event.clear()
179 EventDispatcher.reset()
180 instru = selector.selectedInstrument
181 if instru :
182 console.info('instrument : %s', instru['name'])
183 console.info('preset : %d', instru['preset'])
184 console.info('bank : %d', instru['bank'])
185 console.info('ajustement octave : %d', instru['octave'])
186 return instru
187
188 def runPlayingScreen(self, songFile, playMode, displayNotes, instrumentDescription) :
189 """ Lance l'écran de jeu principal avec la chanson 'songFile' dans le mode 'playMode'
190 avec l'instrument midi 'instrumentDescription'.
191 """
192 playMode = PLAYING_MODES_DICT[playMode]
193 bank, preset = instrumentDescription['bank'], instrumentDescription['preset']
194 octave = instrumentDescription['octave']
195 self.synth.adjust_octave(0, octave)
196 self.synth.program_select(0, bank, preset)
197 if playMode == PLAYING_MODES_DICT['IMPRO'] :
198 playingScreen = PlayingScreen(self.synth, displayNotes=displayNotes)
199 else :
200 song = musicXml2Song(songFile)
201 self.playingScreen = playingScreen = SongPlayingScreen(self.synth, song, mode=playMode, displayNotes=displayNotes)
202 playingScreen.run()
203 pygame.event.clear()
204 EventDispatcher.reset()
205 self.playingScreen = None
206
207
208 class _WTFacade :
209 """ Classe utilitaire pour singer l'api
210 de pygame_wiimouse en cas d'abscence de wiimote.
211 """
212 selectWimoteIndex = 0
213 def pause(self):
214 pass
215 def resume(self):
216 pass
217 def selectWiimote(self, i):
218 pass
219 def get_count(self) :
220 return None