--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/commonappservices/alarmserver/Server/Source/ASSrvSoundController.cpp Tue Feb 02 10:12:00 2010 +0200
@@ -0,0 +1,745 @@
+// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include "ASSrvSoundController.h"
+
+// System includes
+
+// User includes
+#include "ASSrvAlarm.h"
+#include "ASSrvAlarmQueue.h"
+#include "ASSrvStaticUtils.h"
+#include "ASSrvSoundSettings.h"
+#include "ASSrvServerWideData.h"
+#include "ASSrvAnyEventManager.h"
+#include "ASSrvSoundControllerObserver.h"
+#include "ASSrvEnvironmentChangeManager.h"
+
+#include "ASSrvIteratorByState.h"
+#include "ASSrvNotificationCoordinator.h"
+
+
+//
+// ----> CASSrvSoundController (source)
+//
+
+ /**
+ * Indicates that the Sound Controller is disabled (ie. no sounds
+ * intervals configured in the rsc file)
+ */
+TBool CASSrvSoundController::IsSoundControllerDisabled() const
+ {
+ return 0==ServerData().SoundSettings().SoundIntervalCount();
+ }
+
+//*************************************************************************************
+CASSrvSoundController::CASSrvSoundController(CASSrvServerWideData& aServerWideData, MASSrvSoundControllerObserver& aObserver)
+: CTimer(CActive::EPriorityUserInput), iServerWideData(aServerWideData), iObserver(aObserver)
+ {
+ iPreviousSoundEvent = MASSrvSoundControllerObserver::ESoundControllerEventPlayNothing;
+ CActiveScheduler::Add(this);
+ }
+
+
+//*************************************************************************************
+CASSrvSoundController::~CASSrvSoundController()
+ {
+ Cancel();
+
+ // It's ok to Cancel these even if we didn't register for the them:
+ ServerData().EnvironmentChangeManager().RequestEnvironmentChangesCancel(*this);
+ ServerData().SoundSettings().NotifySoundSettingsChangeCancel(*this);
+ ServerData().Queue().RequestAlarmObservationEventsCancel(*this);
+ ServerData().Queue().NotificationPoolChangeCancel(*this);
+ }
+
+
+//*************************************************************************************
+void CASSrvSoundController::ConstructL()
+ {
+ CTimer::ConstructL();
+
+ if( !IsSoundControllerDisabled() )
+ {
+ ServerData().Queue().NotificationPoolChangeL(*this);
+ ServerData().Queue().RequestAlarmObservationEventsL(*this);
+ ServerData().SoundSettings().NotifySoundSettingsChangeL(*this);
+ ServerData().EnvironmentChangeManager().RequestEnvironmentChangesL(*this);
+ iPreviousUTCOffset = User::UTCOffset();
+ iSoundControllerFlags.Set(ESoundControllerFlagsIsFixed);
+ }
+ }
+
+
+//*************************************************************************************
+CASSrvSoundController* CASSrvSoundController::NewL(CASSrvServerWideData& aServerWideData, MASSrvSoundControllerObserver& aObserver)
+ {
+ CASSrvSoundController* self = new(ELeave) CASSrvSoundController(aServerWideData, aObserver);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+
+//
+//
+//
+
+
+//*************************************************************************************
+/**
+ * @see MASSrvAlarmObserver
+ *
+ * When an alarm expires, we should start timing the alarm sound intervals. Note that
+ * no sound is played directly by the alarm server - it's all handled by proxy in the
+ * EikSrv thread (Alarm Alert Server).
+ *
+ * We only ever receive one notification that an alarm has expired (unless its snoozed
+ * and then the snooze expires). Therefore, the sound controller has to perform cycle
+ * management for the alerting (notifying) head alarm in the queue).
+ */
+void CASSrvSoundController::MASSrvAlarmObsHandleEvent(TObserverEvent aEvent, const TASSrvAlarm& aAlarm, TInt aEventSpecificData)
+ {
+ // Get a modifiable version of the alarm
+ TASSrvAlarm* alarm = ServerData().Queue().QueueAlarmById(aAlarm.Id());
+
+ if (aEvent == EAlarmObserverStateChanged)
+ {
+ // Notifying / snoozed / notified / etc
+ const TAlarmState oldState = static_cast<TAlarmState>(aEventSpecificData);
+ if (oldState == EAlarmStateNotifying && IdOfNotifyingAlarm() == aAlarm.Id())
+ {
+ // If the alarm was notifying, but now it's back in the queue
+ // then we need to cancel any sound playing in preparation for
+ // the new notifying alarm
+ if (!InQuietPeriod())
+ {
+ Cancel();
+ }
+
+ if (SoundIsPausedForAlarm())
+ {
+ iSoundControllerFlags.Clear(ESoundControllerFlagsPausing);
+ }
+
+ // Reset this now
+ IdOfNotifyingAlarm() = KNullAlarmId;
+ }
+ //
+ switch(aAlarm.State())
+ {
+ case EAlarmStateNotifying:
+ {
+ // The only thing we really care about is that the new notifying alarm is not null.
+ __ASSERT_DEBUG(aAlarm.Id() != KNullAlarmId,
+ ASSrvStaticUtils::Panic(ASSrvStaticUtils::EASSrvPanicQueueAlarmIdNull));
+
+ // Ensure Alarm Disabled status change didn't slip in ahead in server queue
+ if (alarm->Status() == EAlarmStatusEnabled)
+ {
+ if (InQuietPeriod())
+ {
+ // delay any sound playing until the quiet period ends
+ alarm->SetSoundState(TASSrvAlarm::ESoundStatePlayingNothing);
+ IdOfNotifyingAlarm() = aAlarm.Id();
+ }
+ else
+ {
+ Cancel();
+
+ // Work out when we should start playing the sound
+ IdOfNotifyingAlarm() = aAlarm.Id();
+ WorkOutAndScheduleForNextSoundCycle();
+ }
+ }
+
+ break;
+ }
+
+ case EAlarmStateWaitingToNotify:
+ case EAlarmStateSnoozed:
+ case EAlarmStateNotified:
+ // An alarm is no longer notifying, this is handle above already
+ break;
+
+ // We're not interested in these kind of events
+ case EAlarmStateQueued:
+ case EAlarmStateInPreparation:
+ return;
+ }
+ }
+ else if (aEvent == EAlarmObserverStatusChanged)
+ {
+ // Enabled / disabled
+ if (aAlarm.Id() == IdOfNotifyingAlarm() && alarm->Status() == EAlarmStatusDisabled)
+ {
+ // Cancel sound & timer
+ if (!InQuietPeriod())
+ {
+ Cancel();
+ }
+
+ // Reset this now
+ IdOfNotifyingAlarm() = KNullAlarmId;
+ }
+ }
+
+ // If there is no alarm playing (b/c the previous playing alarm is snoozed,
+ // notified, disabled etc), but there are multiple notifying alarms,
+ // restart sound playing sequence for another notifying alarm
+ if (IdOfNotifyingAlarm() == KNullAlarmId && !InQuietPeriod())
+ {
+ PlayPreviousNotifyingAlarm();
+ }
+ }
+
+
+//
+//
+//
+
+
+//*************************************************************************************
+/**
+ * @see MASSrvSoundSettingsObserver
+ */
+void CASSrvSoundController::MASSoundSettingsHandleChangeEvent(TSoundSettingsEvent aEvent)
+ {
+ CASSrvSoundSettings& soundSettings = ServerData().SoundSettings();
+ //
+ switch(aEvent)
+ {
+ case ESoundSettingsEventGlobalSoundState:
+ if (soundSettings.GlobalSoundState() == EAlarmGlobalSoundStateOff)
+ {
+ // Stop playing anything right now
+ CancelAllSounds();
+ }
+ else
+ {
+ // Resume sound timing from now
+ iTimeToReturnToNormalSoundTimingBehaviour = ASSrvStaticUtils::UtcTimeNow();
+
+ StartSoundTimingForAnyWaitingAlarmAfterPausingOrQuietPeriod();
+ }
+
+ break;
+
+ case ESoundSettingsEventSoundIntervals:
+ // Resume sound timing from now
+ CancelAllSounds();
+ iTimeToReturnToNormalSoundTimingBehaviour = ASSrvStaticUtils::UtcTimeNow();
+
+ StartSoundTimingForAnyWaitingAlarmAfterPausingOrQuietPeriod();
+ break;
+
+ case ESoundSettingsClearPauseFlag:
+ iSoundControllerFlags.Clear(ESoundControllerFlagsPausing);
+ break;
+
+ default:
+ ASSrvStaticUtils::Panic(ASSrvStaticUtils::EASSrvPanicInvalidTSoundSettingsEvent);
+ break;
+ }
+ }
+
+
+//
+//
+//
+
+
+//*************************************************************************************
+/**
+ * @see MASSrvAlarmQueueObserver
+ */
+void CASSrvSoundController::MAlarmQueueObserverHandleEvent(TASSrvAlarmQueueEvent aEvent, TAlarmId aAlarmId)
+ {
+ /* If a notifying alarm is deleted stop playing alarm sound.
+ * Looking for either:
+ * 1. The currently Notifying alarm is deleted.
+ * 2. Alarm Queue Internalize starts whilst any alarm is notifying
+ */
+ if ((aEvent == EASSrvAlarmQueueEventAlarmDeleted) && (aAlarmId == IdOfNotifyingAlarm()))
+ {
+ // Cancel the sound and timer, and clear the id of the alarm (we're
+ // no longer notifying about anything).
+ // Cancel sound & timer
+ if (!InQuietPeriod())
+ {
+ Cancel();
+ }
+
+ IdOfNotifyingAlarm() = KNullAlarmId;
+
+ // If a notifying alarm is deleted, look for the previous notifying alarm.
+ // The following function is called even if we are in quiet period
+ // because we want the appropriate alarm to be played when quite period end.
+ PlayPreviousNotifyingAlarm();
+ }
+ else if ((aEvent == EASSrvAlarmQueueEventAlarmStartInternalize) && (KNullAlarmId != IdOfNotifyingAlarm()))
+ {
+ // Cancel the sound and timer, and clear the id of the alarm (we're
+ // no longer notifying about anything).
+ // Cancel sound & timer
+ if (!InQuietPeriod())
+ {
+ Cancel();
+ }
+
+ IdOfNotifyingAlarm() = KNullAlarmId;
+ }
+ }
+
+//*************************************************************************************
+/**
+ * @see MASSrvEnvironmentChangeObserver
+ */
+
+void CASSrvSoundController::MEnvChangeHandleEvent(TInt aChanges, TUint /*aWorkdays*/, TBool /*aWorkdaysChanged*/)
+ {
+ if (aChanges & EChangesSystemTime || (aChanges & EChangesLocale && (iPreviousUTCOffset != User::UTCOffset())) )
+ {
+ // UTC offset might have changed we need to redo the CTimer::AtUTC with a new UTC offset computed
+
+ if (!iSoundControllerFlags.IsSet(ESoundControllerFlagsIsFixed)) // if floating period
+ {
+ iTimeToReturnToNormalSoundTimingBehaviour -= TTimeIntervalSeconds(User::UTCOffset().Int() - iPreviousUTCOffset.Int());
+ }
+ else //if fixed period
+ {
+ //cancel silent period because we can't recalculate it
+ iTimeToReturnToNormalSoundTimingBehaviour = ASSrvStaticUtils::UtcTimeNow();
+ }
+
+ if (InQuietPeriod() || SoundIsPausedForAlarm())
+ {
+ Cancel();
+
+ if(iTimeToReturnToNormalSoundTimingBehaviour <= ASSrvStaticUtils::UtcTimeNow())
+ {
+ ReactToSoundTimerExpiry(); // Silent period expired
+ }
+ else
+ {
+ AtUTC(iTimeToReturnToNormalSoundTimingBehaviour);
+ }
+ }
+ else if (IdOfNotifyingAlarm() != KNullAlarmId)
+ {
+ // resume sound timing from now because of changed system time
+ StartSoundTimingForAnyWaitingAlarmAfterPausingOrQuietPeriod();
+ }
+
+ // And update the UTC offset
+ iPreviousUTCOffset = User::UTCOffset();
+ }
+ }
+
+
+//
+//
+//
+
+
+//*************************************************************************************
+/**
+ * Stops any sound from playing and resets the sound timer to an idle state.
+ */
+void CASSrvSoundController::CancelAllSounds()
+ {
+ // Tell observer to stop
+ if( !IsSoundControllerDisabled() )
+ {
+ NotifySoundEvent(MASSrvSoundControllerObserver::ESoundControllerEventPlayNothing, IdOfNotifyingAlarm());
+ }
+ }
+
+
+//*************************************************************************************
+/**
+ * Stop playing any sounds until the specified time.
+ */
+void CASSrvSoundController::MakeAllSoundsQuietUntil(const TTime& aTime)
+ {
+ if( IsSoundControllerDisabled() )
+ {
+ return;
+ }
+
+ Cancel();
+
+ // Update the flags
+ iSoundControllerFlags.Set(ESoundControllerFlagsInQuietPeriod);
+
+ // set global sound state
+ ServerData().SoundSettings().SetGlobalSoundState(EAlarmGlobalSoundStateOff);
+
+ // Wake up when sounds are to start again
+ iTimeToReturnToNormalSoundTimingBehaviour = aTime;
+ AtUTC(iTimeToReturnToNormalSoundTimingBehaviour);
+
+ // Notify change
+ ServerData().AnyEventManager().MASAnyEventManagerObserverNotifyChanges(EAlarmChangeEventSoundSilence, KNullAlarmId);
+ }
+
+//*************************************************************************************
+/**
+ * Stop playing the sound (for just this alarm) until the specified time.
+ */
+void CASSrvSoundController::CurrentAlarmSoundPausedUntil(const TTime& aTime)
+ {
+ if( IsSoundControllerDisabled() )
+ {
+ return;
+ }
+
+ Cancel();
+
+ // Save the time we're supposed to wake up at and reset
+ // the alarm's sound state so that it can start over
+ // again when we're due to run.
+ TASSrvAlarm* alarm = ServerData().Queue().QueueAlarmById(IdOfNotifyingAlarm());
+
+ // We have a new baseline for all sound timing calculations. The next set of
+ // cycle calcs must be based upon the time at which the quiet period ends
+ // rather than the original due time.
+ alarm->ReinitializeSoundState(aTime);
+
+ // Update the flags
+ iSoundControllerFlags.Set(ESoundControllerFlagsPausing);
+
+ // Wake up when sounds are to start again
+ iTimeToReturnToNormalSoundTimingBehaviour = aTime;
+
+ AtUTC(aTime);
+
+ // Notify change
+ ServerData().AnyEventManager().MASAnyEventManagerObserverNotifyChanges(EAlarmChangeEventSoundSilence, KNullAlarmId);
+ }
+
+
+//*************************************************************************************
+/**
+ * Returns a boolean indicating whether or not the alarm server is currently
+ * in a quiet period.
+ */
+TBool CASSrvSoundController::InQuietPeriod() const
+ {
+ if( IsSoundControllerDisabled() )
+ {
+ return ETrue;
+ }
+ return Flags().IsSet(ESoundControllerFlagsInQuietPeriod);
+ }
+
+
+//*************************************************************************************
+/**
+ * Return a boolean indicating whether sound is currently
+ * paused within the alarm server.
+ */
+TBool CASSrvSoundController::SoundIsPausedForAlarm() const
+ {
+ if( IsSoundControllerDisabled() )
+ {
+ return EFalse;
+ }
+ return Flags().IsSet(ESoundControllerFlagsPausing);
+ }
+
+
+//*************************************************************************************
+/**
+ * Cancel a previously enabled silent period
+ */
+void CASSrvSoundController::CancelSilence()
+ {
+ if( IsSoundControllerDisabled() )
+ {
+ return;
+ }
+
+ if (iSoundControllerFlags.IsSet(ESoundControllerFlagsPausing) || iSoundControllerFlags.IsSet(ESoundControllerFlagsInQuietPeriod))
+ {
+ Cancel();
+
+ // Update the time to use as a baseline for the next bout of sounds
+ iTimeToReturnToNormalSoundTimingBehaviour = ASSrvStaticUtils::UtcTimeNow();
+
+ // Update the flags
+ iSoundControllerFlags.Clear(ESoundControllerFlagsPausing);
+ iSoundControllerFlags.Clear(ESoundControllerFlagsInQuietPeriod);
+
+ // set global sound state
+ ServerData().SoundSettings().SetGlobalSoundState(EAlarmGlobalSoundStateOn);
+
+ // Notify change
+ ServerData().AnyEventManager().MASAnyEventManagerObserverNotifyChanges(EAlarmChangeEventSoundSilence, KNullAlarmId);
+ }
+ }
+
+
+//
+//
+//
+
+
+//*************************************************************************************
+/**
+ * @see CActive
+ */
+void CASSrvSoundController::RunL()
+ {
+ const TInt statusValue = iStatus.Int();
+
+ // When the user changes the system time, then the timer's request status
+ // is completed with KErrAbort. If we don't gracefully trap this here, then
+ // lots of strange thing start to happen (dialogs don't get dismissed in EikSrv etc).
+ if (statusValue == KErrAbort || statusValue == KErrCancel || statusValue == KErrOverflow)
+ return;
+
+ // Handle the timer expiry
+ ReactToSoundTimerExpiry();
+ }
+
+
+//*************************************************************************************
+/**
+ * Replacement of CActive::Cancel function
+ */
+void CASSrvSoundController::Cancel()
+ {
+ // If we're currently timing an event, Cancel the timer and send
+ // a StopSound command. Otherwise, don't pollute the Alert Server
+ // with an extra message.
+ if( IsActive() )
+ {
+ CTimer::Cancel();
+ CancelAllSounds();
+ }
+ }
+
+
+//
+//
+//
+
+
+//*************************************************************************************
+void CASSrvSoundController::ReactToSoundTimerExpiry()
+ {
+ __ASSERT_DEBUG(!IsSoundControllerDisabled(), ASSrvStaticUtils::Panic(ASSrvStaticUtils::EASSrvPanicUnexpectedEventSoundControllerDisabled));
+
+ if (InQuietPeriod())
+ {
+ // If we're in a quiet period, and the sound timer has expired,
+ // then we should now start to play sound for any currently notifying
+ // alarm.
+ iSoundControllerFlags.Clear(ESoundControllerFlagsInQuietPeriod);
+ ServerData().SoundSettings().SetGlobalSoundState(EAlarmGlobalSoundStateOn);
+ }
+ else if (SoundIsPausedForAlarm())
+ {
+ iSoundControllerFlags.Clear(ESoundControllerFlagsPausing);
+ StartSoundTimingForAnyWaitingAlarmAfterPausingOrQuietPeriod();
+ }
+ else
+ {
+ // ensure notifying Alarm hasn't been disabled, etc... between Timer expiry and this function running
+ if(IdOfNotifyingAlarm() != KNullAlarmId)
+ {
+ WorkOutAndScheduleForNextSoundCycle();
+ }
+ else
+ {
+ // stop any sound currently playing
+ CancelAllSounds();
+ }
+ }
+ }
+
+
+//*************************************************************************************
+void CASSrvSoundController::NotifySoundEvent(MASSrvSoundControllerObserver::TSoundControllerEvent aEvent, TAlarmId aAlarmId)
+ {
+ __ASSERT_DEBUG(!IsSoundControllerDisabled(), ASSrvStaticUtils::Panic(ASSrvStaticUtils::EASSrvPanicUnexpectedEventSoundControllerDisabled));
+
+ if (aEvent == MASSrvSoundControllerObserver::ESoundControllerEventPlaySound &&
+ (InQuietPeriod() || SoundIsPausedForAlarm()))
+ {
+ // If we're in a quiet period, then we should ignore play sound requests...
+ return;
+ }
+ else if (ServerData().SoundSettings().GlobalSoundState() == EAlarmGlobalSoundStateOff)
+ {
+ // Also ignore sounds requests if all sounds are disabled
+ return;
+ }
+
+ // In an effort to minimise the polution passed to the Alert Server, let's
+ // keep track of what message was last sent, except the SoundStopAll events.
+ if ( MASSrvSoundControllerObserver::ESoundControllerEventPlayNothing == aEvent && aAlarmId == KNullAlarmId )
+ {
+ iObserver.MASHandleSoundControllerEvent(aEvent, aAlarmId);
+ }
+ else if ( iPreviousSoundEvent != aEvent )
+ {
+ iPreviousSoundEvent = aEvent;
+ iObserver.MASHandleSoundControllerEvent(aEvent, aAlarmId);
+ }
+ }
+
+
+//*************************************************************************************
+void CASSrvSoundController::StartSoundTimingForAnyWaitingAlarmAfterPausingOrQuietPeriod()
+ {
+ __ASSERT_DEBUG(!IsSoundControllerDisabled(), ASSrvStaticUtils::Panic(ASSrvStaticUtils::EASSrvPanicUnexpectedEventSoundControllerDisabled));
+
+ const TAlarmId id = IdOfNotifyingAlarm();
+ if (id != KNullAlarmId)
+ {
+ // Cancel function of this object is overridden and sends
+ // ESoundControllerEventPlayNothing message as well as Cancels the timer.
+ // The situation that the timer is pending is very unlikely, so we check
+ // if it is Active to prevent unnecessary message pollution.
+ if (IsActive())
+ {
+ Cancel();
+ }
+
+ // Save the time we're supposed to wake up at and reset
+ // the alarm's sound state so that it can start over
+ // again when we're due to run.
+ TASSrvAlarm* alarm = ServerData().Queue().QueueAlarmById(id);
+
+ // Clear the sound paused flag for the notifying alarm
+ alarm->ClearSoundPausedFlag();
+
+ // We have a new baseline for all sound timing calculations. The next set of
+ // cycle calcs must be based upon the time at which the quiet period ends
+ // rather than the original due time.
+ alarm->ReinitializeSoundState(iTimeToReturnToNormalSoundTimingBehaviour);
+
+ // Is a fixed value, should not be recomputed if offset changes.
+ iSoundControllerFlags.Set(ESoundControllerFlagsIsFixed);
+
+ // Run again straight away - this will start the sound again immediately.
+ AtUTC(iTimeToReturnToNormalSoundTimingBehaviour);
+ }
+ }
+
+
+//*************************************************************************************
+void CASSrvSoundController::WorkOutAndScheduleForNextSoundCycle()
+ {
+ __ASSERT_DEBUG(!IsSoundControllerDisabled(), ASSrvStaticUtils::Panic(ASSrvStaticUtils::EASSrvPanicUnexpectedEventSoundControllerDisabled));
+
+ __ASSERT_ALWAYS(IdOfNotifyingAlarm() != KNullAlarmId, ASSrvStaticUtils::Panic(ASSrvStaticUtils::EASSrvPanicNotifyingAboutWrongAlarm));
+
+ const TAlarmId id = IdOfNotifyingAlarm();
+
+
+ // Get the alarm which we are monitoring...
+ TASSrvAlarm* alarm = ServerData().Queue().QueueAlarmById(id);
+
+
+ // Tell observer what to do
+ MASSrvSoundControllerObserver::TSoundControllerEvent event = MASSrvSoundControllerObserver::ESoundControllerEventPlaySound;
+ if (alarm->SoundState() == TASSrvAlarm::ESoundStatePlayingNothing)
+ event = MASSrvSoundControllerObserver::ESoundControllerEventPlayNothing;
+ NotifySoundEvent(event, id);
+
+ // Work out when we're next due to play [sound/silence]
+ const TTime nextTimePeriod = alarm->CalculateAndPrepareNextSoundCycle();
+
+ if (nextTimePeriod == Time::NullTTime())
+ {
+ // We've reached the end of the Sound Interval sequence, with the
+ // Sound Setting Repeat option set to EAlarmSoundRepeatSettingStop.
+ // Reset the Alarm Id and *don't* start the timer.
+ IdOfNotifyingAlarm() = KNullAlarmId;
+ }
+ else
+ {
+ // Toggle the alarm's sound state so that when we wake up, we do the right thing
+ alarm->ToggleSoundState();
+
+ // Next time to react is a fixed offset to UTC
+ iSoundControllerFlags.Set(ESoundControllerFlagsIsFixed);
+
+ // Wait for the next time to react
+ AtUTC(nextTimePeriod);
+ }
+ }
+
+
+/**
+Silent sound if the given alarm id is the currently playing alarm.
+Handles EASAltAlertServerResponseSilence.
+*/
+void CASSrvSoundController::CancelSound(TAlarmId aAlarmId)
+ {
+ // Don't notify anyone if we're disabled.
+ if( IsSoundControllerDisabled() )
+ {
+ return;
+ }
+
+ if ( aAlarmId == KNullAlarmId )
+ {
+ NotifySoundEvent(MASSrvSoundControllerObserver::ESoundControllerEventPlayNothing, aAlarmId);
+ }
+ else if ( aAlarmId == IdOfNotifyingAlarm() )
+ {
+ NotifySoundEvent(MASSrvSoundControllerObserver::ESoundControllerEventPlayNothing, aAlarmId);
+ }
+ }
+
+/**
+If there are other alarm in the notifying alarm list, start sound play
+sequence for the previous notifying alarm. If we are in quite period, this previous
+alarm will be played after quite period ends
+*/
+void CASSrvSoundController::PlayPreviousNotifyingAlarm()
+ {
+ CASSrvAlarmQueue& queue = ServerData().Queue();
+
+ TASSrvAlarm* lastAlarm = NULL;
+ RASSrvIteratorByState iterator(queue, EAlarmStateNotifying);
+ iterator.Open();
+ if (!iterator.NextAlarmAvailable())
+ {
+ return;
+ }
+
+ // look for a the latest alarm
+ while (iterator.NextAlarmAvailable())
+ {
+ lastAlarm = &iterator.NextAlarm();
+ }
+
+ IdOfNotifyingAlarm() = lastAlarm->Id();
+
+ if (!InQuietPeriod())
+ {
+ // reset the baseline for all sound timing calculations.
+ TTime now(ASSrvStaticUtils::UtcTimeNow());
+ lastAlarm->ReinitializeSoundState(now);
+ WorkOutAndScheduleForNextSoundCycle();
+ }
+ }
+