source: src/mlx/soundsched.py@ 182:dd806c3cc18d

Last change on this file since 182:dd806c3cc18d was 176:cb593ff93551, checked in by István Váradi <ivaradi@…>, 13 years ago

Checklist playback seems to work

File size: 9.1 KB
Line 
1# Module to schedule the sounds to be played
2
3#------------------------------------------------------------------------------
4
5from sound import startSound
6import const
7import fs
8
9import threading
10
11#------------------------------------------------------------------------------
12
13class Sound(object):
14 """A sound (file) that should be played in certain circumstances."""
15
16 # Common lock for sounds
17 _lock = threading.Lock()
18
19 def __init__(self, name):
20 """Construct the sound object for the sound file with the given
21 name."""
22 self._name = name
23
24 self._playing = 0
25
26 @property
27 def playing(self):
28 """Determine if sound is playing or not."""
29 return self._playing>0
30
31 def check(self, flight, state, pilotHotkeyPressed):
32 """Check if the file should be played, and if it should be, play it."""
33 if self.shouldPlay(flight, state, pilotHotkeyPressed):
34 with Sound._lock:
35 self._playing += 1
36 startSound(self._name, finishCallback = self._playbackDone)
37
38 def shouldPlay(self, flight, state, pilotHotkeyPressed):
39 """Determine if the sound should be played.
40
41 This default implementation returns False."""
42 return False
43
44 def _playbackDone(self, success, extra):
45 """Called when the playback of thee sound has finished (or failed)."""
46 if success is None:
47 print "Failed to start sound", self._name
48 elif not success:
49 print "Failed to finish sound", self._name
50 with Sound._lock:
51 self._playing -= 1
52
53#------------------------------------------------------------------------------
54
55class ScreamSound(Sound):
56 """A screaming sound that is played under certain circumstance."""
57 def __init__(self):
58 """Construct the screaming sound."""
59 super(ScreamSound, self).__init__(const.SOUND_SCREAM)
60
61 def shouldPlay(self, flight, state, pilotHotkeyPressed):
62 """Determine if the sound should be played.
63
64 It should be played if it is not being played and the absolute value of
65 the vertical speed is greater than 6000 fpm."""
66 return not self.playing and abs(state.vs)>6000
67
68#------------------------------------------------------------------------------
69
70class SimpleSound(Sound):
71 """A simple sound that should be played only once, in a certain flight
72 stage when the hotkey has been pressed or it is not the pilot who controls
73 the sounds.
74
75 If it is not the pilot who controls the sounds, it may be delayed relative
76 to the first detection of a certain flight stage."""
77 def __init__(self, name, stage, delay = 0.0, extraCondition = None,
78 considerHotkey = True, previousSound = None):
79 """Construct the simple sound."""
80 super(SimpleSound, self).__init__(name)
81
82 self._stage = stage
83 self._delay = delay
84 self._extraCondition = extraCondition
85 self._considerHotkey = considerHotkey
86 self._previousSound = previousSound
87
88 self._played = False
89 self._stageDetectionTime = None
90
91 def shouldPlay(self, flight, state, pilotHotkeyPressed):
92 """Determine if the sound should be played."""
93 if flight.stage!=self._stage or self._played or \
94 (self._previousSound is not None and
95 self._previousSound.playing):
96 return False
97
98 toPlay = False
99 if flight.config.pilotControlsSounds and self._considerHotkey:
100 toPlay = pilotHotkeyPressed
101 else:
102 if self._stageDetectionTime is None:
103 self._stageDetectionTime = state.timestamp
104 toPlay = state.timestamp>=(self._stageDetectionTime + self._delay)
105 if toPlay and self._extraCondition is not None:
106 toPlay = self._extraCondition(flight, state)
107
108 if toPlay:
109 self._played = True
110
111 return toPlay
112
113#------------------------------------------------------------------------------
114
115class TaxiSound(SimpleSound):
116 """The taxi sound.
117
118 It first plays the Malev theme song, then an aircraft-specific taxi
119 sound. The playback is started only, if the boarding sound is not being
120 played."""
121
122 _sounds = { const.AIRCRAFT_B736 : const.SOUND_TAXI_BOEING737NG,
123 const.AIRCRAFT_B737 : const.SOUND_TAXI_BOEING737NG,
124 const.AIRCRAFT_B738 : const.SOUND_TAXI_BOEING737NG,
125 const.AIRCRAFT_B762 : const.SOUND_TAXI_BOEING767,
126 const.AIRCRAFT_B763 : const.SOUND_TAXI_BOEING767,
127 const.AIRCRAFT_F70 : const.SOUND_TAXI_F70 }
128
129 def __init__(self, flight, boardingSound = None):
130 """Construct the taxi sound."""
131 super(TaxiSound, self).__init__(const.SOUND_MALEV,
132 const.STAGE_PUSHANDTAXI,
133 previousSound = boardingSound,
134 extraCondition = lambda _flight, state:
135 state.groundSpeed>5)
136
137 self._flight = flight
138
139 def _playbackDone(self, success, extra):
140 """Called when the playback is done.
141
142 It starts playing the aircraft type-specific taxi sound, if any."""
143 super(TaxiSound, self)._playbackDone(success, extra)
144 aircraftType = self._flight.aircraftType
145 sounds = TaxiSound._sounds
146 if aircraftType in sounds:
147 startSound(sounds[aircraftType])
148
149#------------------------------------------------------------------------------
150
151class TouchdownApplause(Sound):
152 """An applause sound that is played after a gentle touchdown."""
153 def __init__(self):
154 super(TouchdownApplause, self).__init__(const.SOUND_APPLAUSE)
155
156 self._touchdownTime = None
157 self._played = False
158
159 def shouldPlay(self, flight, state, pilotHotkeyPressed):
160 """Determine if the sound should be played.
161
162 It should be played if we are 2 seconds after a gentle touchdown."""
163 if self._played or flight.tdRate is None:
164 return False
165
166 if self._touchdownTime is None:
167 self._touchdownTime = state.timestamp
168
169 if state.timestamp>=(self._touchdownTime + 2) and \
170 flight.tdRate<150:
171 self._played = True
172 return True
173 else:
174 return False
175
176#------------------------------------------------------------------------------
177
178class SoundScheduler(object):
179 """A scheduler for the sounds."""
180 def __init__(self, flight):
181 """Construct the sound scheduler for the given flight."""
182 self._flight = flight
183 self._sounds = []
184
185 self._sounds.append(ScreamSound())
186
187 boardingSound = SimpleSound(const.SOUND_BOARDING,
188 const.STAGE_BOARDING,
189 delay = 10.0)
190 self._sounds.append(boardingSound)
191 self._sounds.append(TaxiSound(flight, boardingSound))
192 self._sounds.append(SimpleSound(const.SOUND_CAPTAIN_TAKEOFF,
193 const.STAGE_TAKEOFF,
194 extraCondition = lambda flight, state:
195 state.landingLightsOn or state.gs>80,
196 considerHotkey = False))
197 self._sounds.append(SimpleSound(const.SOUND_CRUISE, const.STAGE_CRUISE))
198 self._sounds.append(SimpleSound(const.SOUND_DESCENT, const.STAGE_DESCENT,
199 extraCondition = lambda flight, state:
200 state.altitude<15000))
201 self._sounds.append(TouchdownApplause())
202 self._sounds.append(SimpleSound(const.SOUND_TAXIAFTERLAND,
203 const.STAGE_TAXIAFTERLAND,
204 delay = 10.0))
205
206 def schedule(self, state, pilotHotkeyPressed):
207 """Schedule any sound, if needed."""
208 flight = self._flight
209 if flight.config.enableSounds:
210 for sound in self._sounds:
211 sound.check(flight, state, pilotHotkeyPressed)
212
213#------------------------------------------------------------------------------
214
215class ChecklistScheduler(object):
216 """A scheduler for the checklist sounds"""
217 def __init__(self, flight):
218 """Construct the checklist scheduler for the given flight."""
219 self._flight = flight
220 self._checklist = None
221 self._itemIndex = 0
222
223 def hotkeyPressed(self):
224 """Called when the checklist hotkey is pressed."""
225 flight = self._flight
226 config = flight.config
227 if config.enableChecklists and flight.aircraftType is not None:
228 if self._checklist is None:
229 self._checklist = config.getChecklist(flight.aircraftType)
230
231 index = self._itemIndex
232 if index>=len(self._checklist):
233 fs.sendMessage(const.MESSAGETYPE_INFORMATION,
234 "End of checklist")
235 else:
236 startSound(self._checklist[index])
237 self._itemIndex += 1
238
239#------------------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.