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