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