|
1 // Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include "ASSrvSoundController.h" |
|
17 |
|
18 // System includes |
|
19 |
|
20 // User includes |
|
21 #include "ASSrvAlarm.h" |
|
22 #include "ASSrvAlarmQueue.h" |
|
23 #include "ASSrvStaticUtils.h" |
|
24 #include "ASSrvSoundSettings.h" |
|
25 #include "ASSrvServerWideData.h" |
|
26 #include "ASSrvAnyEventManager.h" |
|
27 #include "ASSrvSoundControllerObserver.h" |
|
28 #include "ASSrvEnvironmentChangeManager.h" |
|
29 |
|
30 #include "ASSrvIteratorByState.h" |
|
31 #include "ASSrvNotificationCoordinator.h" |
|
32 |
|
33 |
|
34 // |
|
35 // ----> CASSrvSoundController (source) |
|
36 // |
|
37 |
|
38 /** |
|
39 * Indicates that the Sound Controller is disabled (ie. no sounds |
|
40 * intervals configured in the rsc file) |
|
41 */ |
|
42 TBool CASSrvSoundController::IsSoundControllerDisabled() const |
|
43 { |
|
44 return 0==ServerData().SoundSettings().SoundIntervalCount(); |
|
45 } |
|
46 |
|
47 //************************************************************************************* |
|
48 CASSrvSoundController::CASSrvSoundController(CASSrvServerWideData& aServerWideData, MASSrvSoundControllerObserver& aObserver) |
|
49 : CTimer(CActive::EPriorityUserInput), iServerWideData(aServerWideData), iObserver(aObserver) |
|
50 { |
|
51 iPreviousSoundEvent = MASSrvSoundControllerObserver::ESoundControllerEventPlayNothing; |
|
52 CActiveScheduler::Add(this); |
|
53 } |
|
54 |
|
55 |
|
56 //************************************************************************************* |
|
57 CASSrvSoundController::~CASSrvSoundController() |
|
58 { |
|
59 Cancel(); |
|
60 |
|
61 // It's ok to Cancel these even if we didn't register for the them: |
|
62 ServerData().EnvironmentChangeManager().RequestEnvironmentChangesCancel(*this); |
|
63 ServerData().SoundSettings().NotifySoundSettingsChangeCancel(*this); |
|
64 ServerData().Queue().RequestAlarmObservationEventsCancel(*this); |
|
65 ServerData().Queue().NotificationPoolChangeCancel(*this); |
|
66 } |
|
67 |
|
68 |
|
69 //************************************************************************************* |
|
70 void CASSrvSoundController::ConstructL() |
|
71 { |
|
72 CTimer::ConstructL(); |
|
73 |
|
74 if( !IsSoundControllerDisabled() ) |
|
75 { |
|
76 ServerData().Queue().NotificationPoolChangeL(*this); |
|
77 ServerData().Queue().RequestAlarmObservationEventsL(*this); |
|
78 ServerData().SoundSettings().NotifySoundSettingsChangeL(*this); |
|
79 ServerData().EnvironmentChangeManager().RequestEnvironmentChangesL(*this); |
|
80 iPreviousUTCOffset = User::UTCOffset(); |
|
81 iSoundControllerFlags.Set(ESoundControllerFlagsIsFixed); |
|
82 } |
|
83 } |
|
84 |
|
85 |
|
86 //************************************************************************************* |
|
87 CASSrvSoundController* CASSrvSoundController::NewL(CASSrvServerWideData& aServerWideData, MASSrvSoundControllerObserver& aObserver) |
|
88 { |
|
89 CASSrvSoundController* self = new(ELeave) CASSrvSoundController(aServerWideData, aObserver); |
|
90 CleanupStack::PushL(self); |
|
91 self->ConstructL(); |
|
92 CleanupStack::Pop(self); |
|
93 return self; |
|
94 } |
|
95 |
|
96 |
|
97 // |
|
98 // |
|
99 // |
|
100 |
|
101 |
|
102 //************************************************************************************* |
|
103 /** |
|
104 * @see MASSrvAlarmObserver |
|
105 * |
|
106 * When an alarm expires, we should start timing the alarm sound intervals. Note that |
|
107 * no sound is played directly by the alarm server - it's all handled by proxy in the |
|
108 * EikSrv thread (Alarm Alert Server). |
|
109 * |
|
110 * We only ever receive one notification that an alarm has expired (unless its snoozed |
|
111 * and then the snooze expires). Therefore, the sound controller has to perform cycle |
|
112 * management for the alerting (notifying) head alarm in the queue). |
|
113 */ |
|
114 void CASSrvSoundController::MASSrvAlarmObsHandleEvent(TObserverEvent aEvent, const TASSrvAlarm& aAlarm, TInt aEventSpecificData) |
|
115 { |
|
116 // Get a modifiable version of the alarm |
|
117 TASSrvAlarm* alarm = ServerData().Queue().QueueAlarmById(aAlarm.Id()); |
|
118 |
|
119 if (aEvent == EAlarmObserverStateChanged) |
|
120 { |
|
121 // Notifying / snoozed / notified / etc |
|
122 const TAlarmState oldState = static_cast<TAlarmState>(aEventSpecificData); |
|
123 if (oldState == EAlarmStateNotifying && IdOfNotifyingAlarm() == aAlarm.Id()) |
|
124 { |
|
125 // If the alarm was notifying, but now it's back in the queue |
|
126 // then we need to cancel any sound playing in preparation for |
|
127 // the new notifying alarm |
|
128 if (!InQuietPeriod()) |
|
129 { |
|
130 Cancel(); |
|
131 } |
|
132 |
|
133 if (SoundIsPausedForAlarm()) |
|
134 { |
|
135 iSoundControllerFlags.Clear(ESoundControllerFlagsPausing); |
|
136 } |
|
137 |
|
138 // Reset this now |
|
139 IdOfNotifyingAlarm() = KNullAlarmId; |
|
140 } |
|
141 // |
|
142 switch(aAlarm.State()) |
|
143 { |
|
144 case EAlarmStateNotifying: |
|
145 { |
|
146 // The only thing we really care about is that the new notifying alarm is not null. |
|
147 __ASSERT_DEBUG(aAlarm.Id() != KNullAlarmId, |
|
148 ASSrvStaticUtils::Panic(ASSrvStaticUtils::EASSrvPanicQueueAlarmIdNull)); |
|
149 |
|
150 // Ensure Alarm Disabled status change didn't slip in ahead in server queue |
|
151 if (alarm->Status() == EAlarmStatusEnabled) |
|
152 { |
|
153 if (InQuietPeriod()) |
|
154 { |
|
155 // delay any sound playing until the quiet period ends |
|
156 alarm->SetSoundState(TASSrvAlarm::ESoundStatePlayingNothing); |
|
157 IdOfNotifyingAlarm() = aAlarm.Id(); |
|
158 } |
|
159 else |
|
160 { |
|
161 Cancel(); |
|
162 |
|
163 // Work out when we should start playing the sound |
|
164 IdOfNotifyingAlarm() = aAlarm.Id(); |
|
165 WorkOutAndScheduleForNextSoundCycle(); |
|
166 } |
|
167 } |
|
168 |
|
169 break; |
|
170 } |
|
171 |
|
172 case EAlarmStateWaitingToNotify: |
|
173 case EAlarmStateSnoozed: |
|
174 case EAlarmStateNotified: |
|
175 // An alarm is no longer notifying, this is handle above already |
|
176 break; |
|
177 |
|
178 // We're not interested in these kind of events |
|
179 case EAlarmStateQueued: |
|
180 case EAlarmStateInPreparation: |
|
181 return; |
|
182 } |
|
183 } |
|
184 else if (aEvent == EAlarmObserverStatusChanged) |
|
185 { |
|
186 // Enabled / disabled |
|
187 if (aAlarm.Id() == IdOfNotifyingAlarm() && alarm->Status() == EAlarmStatusDisabled) |
|
188 { |
|
189 // Cancel sound & timer |
|
190 if (!InQuietPeriod()) |
|
191 { |
|
192 Cancel(); |
|
193 } |
|
194 |
|
195 // Reset this now |
|
196 IdOfNotifyingAlarm() = KNullAlarmId; |
|
197 } |
|
198 } |
|
199 |
|
200 // If there is no alarm playing (b/c the previous playing alarm is snoozed, |
|
201 // notified, disabled etc), but there are multiple notifying alarms, |
|
202 // restart sound playing sequence for another notifying alarm |
|
203 if (IdOfNotifyingAlarm() == KNullAlarmId && !InQuietPeriod()) |
|
204 { |
|
205 PlayPreviousNotifyingAlarm(); |
|
206 } |
|
207 } |
|
208 |
|
209 |
|
210 // |
|
211 // |
|
212 // |
|
213 |
|
214 |
|
215 //************************************************************************************* |
|
216 /** |
|
217 * @see MASSrvSoundSettingsObserver |
|
218 */ |
|
219 void CASSrvSoundController::MASSoundSettingsHandleChangeEvent(TSoundSettingsEvent aEvent) |
|
220 { |
|
221 CASSrvSoundSettings& soundSettings = ServerData().SoundSettings(); |
|
222 // |
|
223 switch(aEvent) |
|
224 { |
|
225 case ESoundSettingsEventGlobalSoundState: |
|
226 if (soundSettings.GlobalSoundState() == EAlarmGlobalSoundStateOff) |
|
227 { |
|
228 // Stop playing anything right now |
|
229 CancelAllSounds(); |
|
230 } |
|
231 else |
|
232 { |
|
233 // Resume sound timing from now |
|
234 iTimeToReturnToNormalSoundTimingBehaviour = ASSrvStaticUtils::UtcTimeNow(); |
|
235 |
|
236 StartSoundTimingForAnyWaitingAlarmAfterPausingOrQuietPeriod(); |
|
237 } |
|
238 |
|
239 break; |
|
240 |
|
241 case ESoundSettingsEventSoundIntervals: |
|
242 // Resume sound timing from now |
|
243 CancelAllSounds(); |
|
244 iTimeToReturnToNormalSoundTimingBehaviour = ASSrvStaticUtils::UtcTimeNow(); |
|
245 |
|
246 StartSoundTimingForAnyWaitingAlarmAfterPausingOrQuietPeriod(); |
|
247 break; |
|
248 |
|
249 case ESoundSettingsClearPauseFlag: |
|
250 iSoundControllerFlags.Clear(ESoundControllerFlagsPausing); |
|
251 break; |
|
252 |
|
253 default: |
|
254 ASSrvStaticUtils::Panic(ASSrvStaticUtils::EASSrvPanicInvalidTSoundSettingsEvent); |
|
255 break; |
|
256 } |
|
257 } |
|
258 |
|
259 |
|
260 // |
|
261 // |
|
262 // |
|
263 |
|
264 |
|
265 //************************************************************************************* |
|
266 /** |
|
267 * @see MASSrvAlarmQueueObserver |
|
268 */ |
|
269 void CASSrvSoundController::MAlarmQueueObserverHandleEvent(TASSrvAlarmQueueEvent aEvent, TAlarmId aAlarmId) |
|
270 { |
|
271 /* If a notifying alarm is deleted stop playing alarm sound. |
|
272 * Looking for either: |
|
273 * 1. The currently Notifying alarm is deleted. |
|
274 * 2. Alarm Queue Internalize starts whilst any alarm is notifying |
|
275 */ |
|
276 if ((aEvent == EASSrvAlarmQueueEventAlarmDeleted) && (aAlarmId == IdOfNotifyingAlarm())) |
|
277 { |
|
278 // Cancel the sound and timer, and clear the id of the alarm (we're |
|
279 // no longer notifying about anything). |
|
280 // Cancel sound & timer |
|
281 if (!InQuietPeriod()) |
|
282 { |
|
283 Cancel(); |
|
284 } |
|
285 |
|
286 IdOfNotifyingAlarm() = KNullAlarmId; |
|
287 |
|
288 // If a notifying alarm is deleted, look for the previous notifying alarm. |
|
289 // The following function is called even if we are in quiet period |
|
290 // because we want the appropriate alarm to be played when quite period end. |
|
291 PlayPreviousNotifyingAlarm(); |
|
292 } |
|
293 else if ((aEvent == EASSrvAlarmQueueEventAlarmStartInternalize) && (KNullAlarmId != IdOfNotifyingAlarm())) |
|
294 { |
|
295 // Cancel the sound and timer, and clear the id of the alarm (we're |
|
296 // no longer notifying about anything). |
|
297 // Cancel sound & timer |
|
298 if (!InQuietPeriod()) |
|
299 { |
|
300 Cancel(); |
|
301 } |
|
302 |
|
303 IdOfNotifyingAlarm() = KNullAlarmId; |
|
304 } |
|
305 } |
|
306 |
|
307 //************************************************************************************* |
|
308 /** |
|
309 * @see MASSrvEnvironmentChangeObserver |
|
310 */ |
|
311 |
|
312 void CASSrvSoundController::MEnvChangeHandleEvent(TInt aChanges, TUint /*aWorkdays*/, TBool /*aWorkdaysChanged*/) |
|
313 { |
|
314 if (aChanges & EChangesSystemTime || (aChanges & EChangesLocale && (iPreviousUTCOffset != User::UTCOffset())) ) |
|
315 { |
|
316 // UTC offset might have changed we need to redo the CTimer::AtUTC with a new UTC offset computed |
|
317 |
|
318 if (!iSoundControllerFlags.IsSet(ESoundControllerFlagsIsFixed)) // if floating period |
|
319 { |
|
320 iTimeToReturnToNormalSoundTimingBehaviour -= TTimeIntervalSeconds(User::UTCOffset().Int() - iPreviousUTCOffset.Int()); |
|
321 } |
|
322 else //if fixed period |
|
323 { |
|
324 //cancel silent period because we can't recalculate it |
|
325 iTimeToReturnToNormalSoundTimingBehaviour = ASSrvStaticUtils::UtcTimeNow(); |
|
326 } |
|
327 |
|
328 if (InQuietPeriod() || SoundIsPausedForAlarm()) |
|
329 { |
|
330 Cancel(); |
|
331 |
|
332 if(iTimeToReturnToNormalSoundTimingBehaviour <= ASSrvStaticUtils::UtcTimeNow()) |
|
333 { |
|
334 ReactToSoundTimerExpiry(); // Silent period expired |
|
335 } |
|
336 else |
|
337 { |
|
338 AtUTC(iTimeToReturnToNormalSoundTimingBehaviour); |
|
339 } |
|
340 } |
|
341 else if (IdOfNotifyingAlarm() != KNullAlarmId) |
|
342 { |
|
343 // resume sound timing from now because of changed system time |
|
344 StartSoundTimingForAnyWaitingAlarmAfterPausingOrQuietPeriod(); |
|
345 } |
|
346 |
|
347 // And update the UTC offset |
|
348 iPreviousUTCOffset = User::UTCOffset(); |
|
349 } |
|
350 } |
|
351 |
|
352 |
|
353 // |
|
354 // |
|
355 // |
|
356 |
|
357 |
|
358 //************************************************************************************* |
|
359 /** |
|
360 * Stops any sound from playing and resets the sound timer to an idle state. |
|
361 */ |
|
362 void CASSrvSoundController::CancelAllSounds() |
|
363 { |
|
364 // Tell observer to stop |
|
365 if( !IsSoundControllerDisabled() ) |
|
366 { |
|
367 NotifySoundEvent(MASSrvSoundControllerObserver::ESoundControllerEventPlayNothing, IdOfNotifyingAlarm()); |
|
368 } |
|
369 } |
|
370 |
|
371 |
|
372 //************************************************************************************* |
|
373 /** |
|
374 * Stop playing any sounds until the specified time. |
|
375 */ |
|
376 void CASSrvSoundController::MakeAllSoundsQuietUntil(const TTime& aTime) |
|
377 { |
|
378 if( IsSoundControllerDisabled() ) |
|
379 { |
|
380 return; |
|
381 } |
|
382 |
|
383 Cancel(); |
|
384 |
|
385 // Update the flags |
|
386 iSoundControllerFlags.Set(ESoundControllerFlagsInQuietPeriod); |
|
387 |
|
388 // set global sound state |
|
389 ServerData().SoundSettings().SetGlobalSoundState(EAlarmGlobalSoundStateOff); |
|
390 |
|
391 // Wake up when sounds are to start again |
|
392 iTimeToReturnToNormalSoundTimingBehaviour = aTime; |
|
393 AtUTC(iTimeToReturnToNormalSoundTimingBehaviour); |
|
394 |
|
395 // Notify change |
|
396 ServerData().AnyEventManager().MASAnyEventManagerObserverNotifyChanges(EAlarmChangeEventSoundSilence, KNullAlarmId); |
|
397 } |
|
398 |
|
399 //************************************************************************************* |
|
400 /** |
|
401 * Stop playing the sound (for just this alarm) until the specified time. |
|
402 */ |
|
403 void CASSrvSoundController::CurrentAlarmSoundPausedUntil(const TTime& aTime) |
|
404 { |
|
405 if( IsSoundControllerDisabled() ) |
|
406 { |
|
407 return; |
|
408 } |
|
409 |
|
410 Cancel(); |
|
411 |
|
412 // Save the time we're supposed to wake up at and reset |
|
413 // the alarm's sound state so that it can start over |
|
414 // again when we're due to run. |
|
415 TASSrvAlarm* alarm = ServerData().Queue().QueueAlarmById(IdOfNotifyingAlarm()); |
|
416 |
|
417 // We have a new baseline for all sound timing calculations. The next set of |
|
418 // cycle calcs must be based upon the time at which the quiet period ends |
|
419 // rather than the original due time. |
|
420 alarm->ReinitializeSoundState(aTime); |
|
421 |
|
422 // Update the flags |
|
423 iSoundControllerFlags.Set(ESoundControllerFlagsPausing); |
|
424 |
|
425 // Wake up when sounds are to start again |
|
426 iTimeToReturnToNormalSoundTimingBehaviour = aTime; |
|
427 |
|
428 AtUTC(aTime); |
|
429 |
|
430 // Notify change |
|
431 ServerData().AnyEventManager().MASAnyEventManagerObserverNotifyChanges(EAlarmChangeEventSoundSilence, KNullAlarmId); |
|
432 } |
|
433 |
|
434 |
|
435 //************************************************************************************* |
|
436 /** |
|
437 * Returns a boolean indicating whether or not the alarm server is currently |
|
438 * in a quiet period. |
|
439 */ |
|
440 TBool CASSrvSoundController::InQuietPeriod() const |
|
441 { |
|
442 if( IsSoundControllerDisabled() ) |
|
443 { |
|
444 return ETrue; |
|
445 } |
|
446 return Flags().IsSet(ESoundControllerFlagsInQuietPeriod); |
|
447 } |
|
448 |
|
449 |
|
450 //************************************************************************************* |
|
451 /** |
|
452 * Return a boolean indicating whether sound is currently |
|
453 * paused within the alarm server. |
|
454 */ |
|
455 TBool CASSrvSoundController::SoundIsPausedForAlarm() const |
|
456 { |
|
457 if( IsSoundControllerDisabled() ) |
|
458 { |
|
459 return EFalse; |
|
460 } |
|
461 return Flags().IsSet(ESoundControllerFlagsPausing); |
|
462 } |
|
463 |
|
464 |
|
465 //************************************************************************************* |
|
466 /** |
|
467 * Cancel a previously enabled silent period |
|
468 */ |
|
469 void CASSrvSoundController::CancelSilence() |
|
470 { |
|
471 if( IsSoundControllerDisabled() ) |
|
472 { |
|
473 return; |
|
474 } |
|
475 |
|
476 if (iSoundControllerFlags.IsSet(ESoundControllerFlagsPausing) || iSoundControllerFlags.IsSet(ESoundControllerFlagsInQuietPeriod)) |
|
477 { |
|
478 Cancel(); |
|
479 |
|
480 // Update the time to use as a baseline for the next bout of sounds |
|
481 iTimeToReturnToNormalSoundTimingBehaviour = ASSrvStaticUtils::UtcTimeNow(); |
|
482 |
|
483 // Update the flags |
|
484 iSoundControllerFlags.Clear(ESoundControllerFlagsPausing); |
|
485 iSoundControllerFlags.Clear(ESoundControllerFlagsInQuietPeriod); |
|
486 |
|
487 // set global sound state |
|
488 ServerData().SoundSettings().SetGlobalSoundState(EAlarmGlobalSoundStateOn); |
|
489 |
|
490 // Notify change |
|
491 ServerData().AnyEventManager().MASAnyEventManagerObserverNotifyChanges(EAlarmChangeEventSoundSilence, KNullAlarmId); |
|
492 } |
|
493 } |
|
494 |
|
495 |
|
496 // |
|
497 // |
|
498 // |
|
499 |
|
500 |
|
501 //************************************************************************************* |
|
502 /** |
|
503 * @see CActive |
|
504 */ |
|
505 void CASSrvSoundController::RunL() |
|
506 { |
|
507 const TInt statusValue = iStatus.Int(); |
|
508 |
|
509 // When the user changes the system time, then the timer's request status |
|
510 // is completed with KErrAbort. If we don't gracefully trap this here, then |
|
511 // lots of strange thing start to happen (dialogs don't get dismissed in EikSrv etc). |
|
512 if (statusValue == KErrAbort || statusValue == KErrCancel || statusValue == KErrOverflow) |
|
513 return; |
|
514 |
|
515 // Handle the timer expiry |
|
516 ReactToSoundTimerExpiry(); |
|
517 } |
|
518 |
|
519 |
|
520 //************************************************************************************* |
|
521 /** |
|
522 * Replacement of CActive::Cancel function |
|
523 */ |
|
524 void CASSrvSoundController::Cancel() |
|
525 { |
|
526 // If we're currently timing an event, Cancel the timer and send |
|
527 // a StopSound command. Otherwise, don't pollute the Alert Server |
|
528 // with an extra message. |
|
529 if( IsActive() ) |
|
530 { |
|
531 CTimer::Cancel(); |
|
532 CancelAllSounds(); |
|
533 } |
|
534 } |
|
535 |
|
536 |
|
537 // |
|
538 // |
|
539 // |
|
540 |
|
541 |
|
542 //************************************************************************************* |
|
543 void CASSrvSoundController::ReactToSoundTimerExpiry() |
|
544 { |
|
545 __ASSERT_DEBUG(!IsSoundControllerDisabled(), ASSrvStaticUtils::Panic(ASSrvStaticUtils::EASSrvPanicUnexpectedEventSoundControllerDisabled)); |
|
546 |
|
547 if (InQuietPeriod()) |
|
548 { |
|
549 // If we're in a quiet period, and the sound timer has expired, |
|
550 // then we should now start to play sound for any currently notifying |
|
551 // alarm. |
|
552 iSoundControllerFlags.Clear(ESoundControllerFlagsInQuietPeriod); |
|
553 ServerData().SoundSettings().SetGlobalSoundState(EAlarmGlobalSoundStateOn); |
|
554 } |
|
555 else if (SoundIsPausedForAlarm()) |
|
556 { |
|
557 iSoundControllerFlags.Clear(ESoundControllerFlagsPausing); |
|
558 StartSoundTimingForAnyWaitingAlarmAfterPausingOrQuietPeriod(); |
|
559 } |
|
560 else |
|
561 { |
|
562 // ensure notifying Alarm hasn't been disabled, etc... between Timer expiry and this function running |
|
563 if(IdOfNotifyingAlarm() != KNullAlarmId) |
|
564 { |
|
565 WorkOutAndScheduleForNextSoundCycle(); |
|
566 } |
|
567 else |
|
568 { |
|
569 // stop any sound currently playing |
|
570 CancelAllSounds(); |
|
571 } |
|
572 } |
|
573 } |
|
574 |
|
575 |
|
576 //************************************************************************************* |
|
577 void CASSrvSoundController::NotifySoundEvent(MASSrvSoundControllerObserver::TSoundControllerEvent aEvent, TAlarmId aAlarmId) |
|
578 { |
|
579 __ASSERT_DEBUG(!IsSoundControllerDisabled(), ASSrvStaticUtils::Panic(ASSrvStaticUtils::EASSrvPanicUnexpectedEventSoundControllerDisabled)); |
|
580 |
|
581 if (aEvent == MASSrvSoundControllerObserver::ESoundControllerEventPlaySound && |
|
582 (InQuietPeriod() || SoundIsPausedForAlarm())) |
|
583 { |
|
584 // If we're in a quiet period, then we should ignore play sound requests... |
|
585 return; |
|
586 } |
|
587 else if (ServerData().SoundSettings().GlobalSoundState() == EAlarmGlobalSoundStateOff) |
|
588 { |
|
589 // Also ignore sounds requests if all sounds are disabled |
|
590 return; |
|
591 } |
|
592 |
|
593 // In an effort to minimise the polution passed to the Alert Server, let's |
|
594 // keep track of what message was last sent, except the SoundStopAll events. |
|
595 if ( MASSrvSoundControllerObserver::ESoundControllerEventPlayNothing == aEvent && aAlarmId == KNullAlarmId ) |
|
596 { |
|
597 iObserver.MASHandleSoundControllerEvent(aEvent, aAlarmId); |
|
598 } |
|
599 else if ( iPreviousSoundEvent != aEvent ) |
|
600 { |
|
601 iPreviousSoundEvent = aEvent; |
|
602 iObserver.MASHandleSoundControllerEvent(aEvent, aAlarmId); |
|
603 } |
|
604 } |
|
605 |
|
606 |
|
607 //************************************************************************************* |
|
608 void CASSrvSoundController::StartSoundTimingForAnyWaitingAlarmAfterPausingOrQuietPeriod() |
|
609 { |
|
610 __ASSERT_DEBUG(!IsSoundControllerDisabled(), ASSrvStaticUtils::Panic(ASSrvStaticUtils::EASSrvPanicUnexpectedEventSoundControllerDisabled)); |
|
611 |
|
612 const TAlarmId id = IdOfNotifyingAlarm(); |
|
613 if (id != KNullAlarmId) |
|
614 { |
|
615 // Cancel function of this object is overridden and sends |
|
616 // ESoundControllerEventPlayNothing message as well as Cancels the timer. |
|
617 // The situation that the timer is pending is very unlikely, so we check |
|
618 // if it is Active to prevent unnecessary message pollution. |
|
619 if (IsActive()) |
|
620 { |
|
621 Cancel(); |
|
622 } |
|
623 |
|
624 // Save the time we're supposed to wake up at and reset |
|
625 // the alarm's sound state so that it can start over |
|
626 // again when we're due to run. |
|
627 TASSrvAlarm* alarm = ServerData().Queue().QueueAlarmById(id); |
|
628 |
|
629 // Clear the sound paused flag for the notifying alarm |
|
630 alarm->ClearSoundPausedFlag(); |
|
631 |
|
632 // We have a new baseline for all sound timing calculations. The next set of |
|
633 // cycle calcs must be based upon the time at which the quiet period ends |
|
634 // rather than the original due time. |
|
635 alarm->ReinitializeSoundState(iTimeToReturnToNormalSoundTimingBehaviour); |
|
636 |
|
637 // Is a fixed value, should not be recomputed if offset changes. |
|
638 iSoundControllerFlags.Set(ESoundControllerFlagsIsFixed); |
|
639 |
|
640 // Run again straight away - this will start the sound again immediately. |
|
641 AtUTC(iTimeToReturnToNormalSoundTimingBehaviour); |
|
642 } |
|
643 } |
|
644 |
|
645 |
|
646 //************************************************************************************* |
|
647 void CASSrvSoundController::WorkOutAndScheduleForNextSoundCycle() |
|
648 { |
|
649 __ASSERT_DEBUG(!IsSoundControllerDisabled(), ASSrvStaticUtils::Panic(ASSrvStaticUtils::EASSrvPanicUnexpectedEventSoundControllerDisabled)); |
|
650 |
|
651 __ASSERT_ALWAYS(IdOfNotifyingAlarm() != KNullAlarmId, ASSrvStaticUtils::Panic(ASSrvStaticUtils::EASSrvPanicNotifyingAboutWrongAlarm)); |
|
652 |
|
653 const TAlarmId id = IdOfNotifyingAlarm(); |
|
654 |
|
655 |
|
656 // Get the alarm which we are monitoring... |
|
657 TASSrvAlarm* alarm = ServerData().Queue().QueueAlarmById(id); |
|
658 |
|
659 |
|
660 // Tell observer what to do |
|
661 MASSrvSoundControllerObserver::TSoundControllerEvent event = MASSrvSoundControllerObserver::ESoundControllerEventPlaySound; |
|
662 if (alarm->SoundState() == TASSrvAlarm::ESoundStatePlayingNothing) |
|
663 event = MASSrvSoundControllerObserver::ESoundControllerEventPlayNothing; |
|
664 NotifySoundEvent(event, id); |
|
665 |
|
666 // Work out when we're next due to play [sound/silence] |
|
667 const TTime nextTimePeriod = alarm->CalculateAndPrepareNextSoundCycle(); |
|
668 |
|
669 if (nextTimePeriod == Time::NullTTime()) |
|
670 { |
|
671 // We've reached the end of the Sound Interval sequence, with the |
|
672 // Sound Setting Repeat option set to EAlarmSoundRepeatSettingStop. |
|
673 // Reset the Alarm Id and *don't* start the timer. |
|
674 IdOfNotifyingAlarm() = KNullAlarmId; |
|
675 } |
|
676 else |
|
677 { |
|
678 // Toggle the alarm's sound state so that when we wake up, we do the right thing |
|
679 alarm->ToggleSoundState(); |
|
680 |
|
681 // Next time to react is a fixed offset to UTC |
|
682 iSoundControllerFlags.Set(ESoundControllerFlagsIsFixed); |
|
683 |
|
684 // Wait for the next time to react |
|
685 AtUTC(nextTimePeriod); |
|
686 } |
|
687 } |
|
688 |
|
689 |
|
690 /** |
|
691 Silent sound if the given alarm id is the currently playing alarm. |
|
692 Handles EASAltAlertServerResponseSilence. |
|
693 */ |
|
694 void CASSrvSoundController::CancelSound(TAlarmId aAlarmId) |
|
695 { |
|
696 // Don't notify anyone if we're disabled. |
|
697 if( IsSoundControllerDisabled() ) |
|
698 { |
|
699 return; |
|
700 } |
|
701 |
|
702 if ( aAlarmId == KNullAlarmId ) |
|
703 { |
|
704 NotifySoundEvent(MASSrvSoundControllerObserver::ESoundControllerEventPlayNothing, aAlarmId); |
|
705 } |
|
706 else if ( aAlarmId == IdOfNotifyingAlarm() ) |
|
707 { |
|
708 NotifySoundEvent(MASSrvSoundControllerObserver::ESoundControllerEventPlayNothing, aAlarmId); |
|
709 } |
|
710 } |
|
711 |
|
712 /** |
|
713 If there are other alarm in the notifying alarm list, start sound play |
|
714 sequence for the previous notifying alarm. If we are in quite period, this previous |
|
715 alarm will be played after quite period ends |
|
716 */ |
|
717 void CASSrvSoundController::PlayPreviousNotifyingAlarm() |
|
718 { |
|
719 CASSrvAlarmQueue& queue = ServerData().Queue(); |
|
720 |
|
721 TASSrvAlarm* lastAlarm = NULL; |
|
722 RASSrvIteratorByState iterator(queue, EAlarmStateNotifying); |
|
723 iterator.Open(); |
|
724 if (!iterator.NextAlarmAvailable()) |
|
725 { |
|
726 return; |
|
727 } |
|
728 |
|
729 // look for a the latest alarm |
|
730 while (iterator.NextAlarmAvailable()) |
|
731 { |
|
732 lastAlarm = &iterator.NextAlarm(); |
|
733 } |
|
734 |
|
735 IdOfNotifyingAlarm() = lastAlarm->Id(); |
|
736 |
|
737 if (!InQuietPeriod()) |
|
738 { |
|
739 // reset the baseline for all sound timing calculations. |
|
740 TTime now(ASSrvStaticUtils::UtcTimeNow()); |
|
741 lastAlarm->ReinitializeSoundState(now); |
|
742 WorkOutAndScheduleForNextSoundCycle(); |
|
743 } |
|
744 } |
|
745 |