95bfaab00b84a3d408afe8f277d204be56abb577
[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
54 def initWiimotes(self) :
55 if self.wiimoteSupport :
56 global wiiuse
57 from pywiiuse import PyWiiUse as wiiuse
58 global pygame_wiimouse
59 from pywiiuse import pygame_wiimouse
60 from minwii.config import IR_POSITION
61 pygame_wiimouse.init(5, 5, self.screenResolution, IR_POSITION) # look for 5, wait 5 seconds
62 self.nwiimotes = nwiimotes = pygame_wiimouse.get_count()
63 console.debug('wiimotes found : %d', nwiimotes)
64 self.WT = WT = pygame_wiimouse.WT
65 WT.setEventCallBack(self._wiimotesEventCallBack)
66 WT.pause()
67 else :
68 self.WT = _WTFacade()
69
70 def _wiimotesEventCallBack(self, wt, id, wmp) :
71 if self.screen == SCREEN_PLAY :
72 pygame_wiimouse._default_event_cb(wt, id, wmp)
73
74 wm = wmp[0]
75 if id == self.nwiimotes - 1 :
76 # le bouton Home de la télécommande permet de sortir
77 # (envoi d'un événement clavier « q »)
78 if wiiuse.is_just_pressed(wm, wiiuse.button['Home']) :
79 event = pygame.event.Event(pygame.KEYDOWN,
80 key = pygame.K_q,
81 unicode = u'q')
82 pygame.event.post(event)
83 elif wiiuse.is_just_pressed(wm, wiiuse.button['+']) :
84 self.synth.inc_gain()
85 elif wiiuse.is_just_pressed(wm, wiiuse.button['-']) :
86 self.synth.dec_gain()
87
88 elif self.screen in (SCREEN_HOME, SCREEN_INSTRUMENTS) :
89 pygame_wiimouse._full_mouse_event_cb(wt, id, wmp)
90
91 def run(self) :
92 "séquençage de l'affichage des écrans"
93 displayFlags = 0
94 if self.fullscreen :
95 displayFlags = displayFlags | pygame.FULLSCREEN
96 pygame.display.set_mode(self.screenResolution, displayFlags)
97 pygame.display.set_caption('MINWii')
98 WT = self.WT
99
100 songFile, playMode, wiimoteIndex = '', 'NORMAL', 0
101
102 while True :
103 WT.resume()
104 WT.selectWiimote(self.nwiimotes - 1) # la télécommande est la souris
105 self.screen = SCREEN_HOME
106 exit, songFile, playMode, wiimoteIndex = \
107 self.selectSongAndOptions(songFile, playMode, wiimoteIndex)
108 if exit : break
109
110
111 self.screen = SCREEN_INSTRUMENTS
112 instrumentDescription = self.selectInstrument()
113 if not instrumentDescription :
114 continue
115
116 self.screen = SCREEN_PLAY
117 WT.selectWiimote(wiimoteIndex)
118 self.runPlayingScreen(songFile, playMode, instrumentDescription)
119 WT.pause()
120
121
122 def selectSongAndOptions(self, songFile, playMode, wiimoteIndex) :
123 """ lance l'écran de paramétrage et retourne un tuple comportant :
124 - drapeau de sortie de l'application (booléen)
125 - chemin du fichier de la chanson
126 - mode (entier)
127 - wiimote sélectionnée (entier)
128 """
129 home = Home(songPath=SONG_FILE_PATH,
130 songFile=songFile,
131 playMode=playMode,
132 wiimoteIndex=wiimoteIndex,
133 nwiimotes=self.nwiimotes)
134 app = self.app
135 home.connect(QUIT, app.quit)
136 app.run(home)
137 app.close(home)
138
139 #logging
140 if home.exitApp :
141 console.debug("sortie de l'application")
142 else :
143 actual_wiimotes = self.WT.get_count()
144 if self.firstSong :
145 self.firstSong = False
146 else :
147 envLogger.info('NEW_LOG_FILE')
148 console.info('chanson : %s', home.songFile)
149 console.info('mode : %s', home.modeSelect.value)
150 if actual_wiimotes is None :
151 console.info('HID : souris')
152 elif actual_wiimotes == 0 :
153 console.info('HID : souris (pas de wiimote trouvée)')
154 else :
155 console.info('HID : wiimote %d', home.selectedWiimote.value + 1)
156 #---
157
158 return (home.exitApp,
159 home.songFile,
160 home.selectedPlayMode,
161 home.selectedWiimoteIndex)
162
163 def selectInstrument(self) :
164 """ lance l'écran de sélection de l'instrument et retourne
165 un dictionnaire comportant la description de l'instrument
166 """
167 selector = InstrumentSelector()
168 selector.run()
169 selector.stop()
170 pygame.event.clear()
171 EventDispatcher.reset()
172 instru = selector.selectedInstrument
173 if instru :
174 console.info('instrument : %s', instru['name'])
175 console.info('preset : %d', instru['preset'])
176 console.info('bank : %d', instru['bank'])
177 console.info('ajustement octave : %d', instru['octave'])
178 return instru
179
180 def runPlayingScreen(self, songFile, playMode, instrumentDescription) :
181 """ Lance l'écran de jeu principal avec la chanson 'songFile' dans le mode 'playMode'
182 avec l'instrument midi 'instrumentDescription'.
183 """
184 playMode = PLAYING_MODES_DICT[playMode]
185 bank, preset = instrumentDescription['bank'], instrumentDescription['preset']
186 octave = instrumentDescription['octave']
187 self.synth.adjust_octave(0, octave)
188 self.synth.program_select(0, bank, preset)
189 if playMode == PLAYING_MODES_DICT['IMPRO'] :
190 playingScreen = PlayingScreen(self.synth)
191 else :
192 song = musicXml2Song(songFile)
193 playingScreen = SongPlayingScreen(self.synth, song, mode=playMode)
194 playingScreen.run()
195 pygame.event.clear()
196 EventDispatcher.reset()
197
198
199 class _WTFacade :
200 """ Classe utilitaire pour singer l'api
201 de pygame_wiimouse en cas d'abscence de wiimote.
202 """
203 selectWimoteIndex = 0
204 def pause(self):
205 pass
206 def resume(self):
207 pass
208 def selectWiimote(self, i):
209 pass
210 def get_count(self) :
211 return None