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