alarmui/src/AlmAlarmPlayer.cpp
author Simon Howkins <simonh@symbian.org>
Mon, 22 Nov 2010 16:01:09 +0000
branchRCL_3
changeset 93 d216ae5a8733
parent 66 bd7edf625bdd
permissions -rw-r--r--
Adjusted to avoid exports, etc, from a top-level bld.inf

/*
* Copyright (c) 2006-2007 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:  This class provides audio playback for Alarm UI.
*
*/



// INCLUDE FILES
#include "AlmAlarmPlayer.h"
#include "alarmutils.h"
#include "pim_trace.h"

#include <AudioPreference.h>

// CONSTANTS AND MACROS
const TInt KSoundInterval( 1000000 );  // 1 second

// set player volume
#define SET_VOLUME( t, v )  t->SetVolume( v );

// Copied from Phone's Toneplayer.
_LIT8( KPhoneBeepSequence, "\x00\x11\x06\x0A\x08\x73\x0A\x40\x28\x0A\xF7\x05\xFC\x40\x64\x0A\x08\x40\x32\x0A\xF7\x06\x0B" );
_LIT8( KPhoneNoSoundSequence, "\x00\x11\x06\x05\xFC\x0A\x08\x40\x32\x0A\xF7\x40\x64\x06\x0B" );


// ============================ MEMBER FUNCTIONS ===============================

// -----------------------------------------------------------------------------
// C++ default constructor.
// -----------------------------------------------------------------------------
//
CAlmAlarmPlayer::CAlmAlarmPlayer(CAlarmUtils* aAlarmUtils)
 : iAlarmUtils( aAlarmUtils )
{
    TRACE_ENTRY_POINT;
    TRACE_EXIT_POINT;
}

// -----------------------------------------------------------------------------
// Symbian 2nd phase constructor.
// -----------------------------------------------------------------------------
//
void CAlmAlarmPlayer::ConstructL(void)
{
    TRACE_ENTRY_POINT;
    PlayAlarmL();
    TRACE_EXIT_POINT;
}

// -----------------------------------------------------------------------------
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CAlmAlarmPlayer* CAlmAlarmPlayer::NewL(CAlarmUtils* aAlarmUtils)
{ // static
    TRACE_ENTRY_POINT;
    CAlmAlarmPlayer* self = new( ELeave )CAlmAlarmPlayer( aAlarmUtils );
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop( self );
    TRACE_EXIT_POINT;
    return self;
}

// -----------------------------------------------------------------------------
// Destructor.
// -----------------------------------------------------------------------------
//
CAlmAlarmPlayer::~CAlmAlarmPlayer(void)
{
    TRACE_ENTRY_POINT;

    if( iSequencePlayer )
    {
        if( iSequencePlayer->State() == EMdaAudioToneUtilityPlaying )
        {
            iSequencePlayer->CancelPlay();
        }
        else
        {
            iSequencePlayer->CancelPrepare();
        }
        delete iSequencePlayer;
    }

    if( iSamplePlayer )
    {
        iSamplePlayer->Stop();
        iSamplePlayer->Close();
        delete iSamplePlayer;
    }

    if( iBeepPlayer )
    {
        if( iBeepPlayer->State() == EMdaAudioToneUtilityPlaying )
        {
            iBeepPlayer->CancelPlay();
        }
        else
        {
            iBeepPlayer->CancelPrepare();
        }
        delete iBeepPlayer;
    }
    TRACE_EXIT_POINT;
}

// -----------------------------------------------------------------------------
// Once tone initialization is complete play the tone.
// -----------------------------------------------------------------------------
//
void CAlmAlarmPlayer::MatoPrepareComplete(TInt aError)
{
    TRACE_ENTRY_POINT;
    if( aError != KErrNone )
    {
        PIM_TRAPD_ASSERT( HandlePlayErrorL( aError ); )
    }
    else if( iBeepPlayer )
    {
        iBeepPlayer->Play();
    }
    else
    {
        iSequencePlayer->Play();
    }
    TRACE_EXIT_POINT;
}

// -----------------------------------------------------------------------------
// Callback for completing tone player.
// -----------------------------------------------------------------------------
//
void CAlmAlarmPlayer::MatoPlayComplete(TInt aError)
{
    TRACE_ENTRY_POINT;
    if( aError != KErrNone )
    {
        PIM_TRAPD_ASSERT( HandlePlayErrorL( aError ); )
    }
    TRACE_EXIT_POINT;
}

// -----------------------------------------------------------------------------
// When initialization is complete set the player settings and play the sound.
// -----------------------------------------------------------------------------
//
void CAlmAlarmPlayer::MapcInitComplete(TInt aError, const TTimeIntervalMicroSeconds& /*aDuration*/)
{
    TRACE_ENTRY_POINT;
    if( aError == KErrNone )
    {
        iSamplePlayer->SetVolumeRamp( TTimeIntervalMicroSeconds( iAlarmUtils->AlarmData().iVolumeRampTime ) );

        iSamplePlayer->SetRepeats( iAlarmUtils->AlarmData().iRepeatValue, 
                                   TTimeIntervalMicroSeconds( KSoundInterval ) );

        SET_VOLUME( iSamplePlayer, 
                    PlayerVolume( iSamplePlayer->MaxVolume(),
                                  iAlarmUtils->AlarmData().iVolume ) )

        iSamplePlayer->Play();
    }
    else
    {
        PIM_TRAPD_ASSERT( HandlePlayErrorL( aError ); )
    }
    TRACE_EXIT_POINT;
}

// -----------------------------------------------------------------------------
// Callback for completing audio player.
// -----------------------------------------------------------------------------
//
void CAlmAlarmPlayer::MapcPlayComplete(TInt aError)
{
    TRACE_ENTRY_POINT;
    if( aError != KErrNone )
    {
        PIM_TRAPD_ASSERT( HandlePlayErrorL( aError ); )
    }
    TRACE_EXIT_POINT;
}

// -----------------------------------------------------------------------------
// Play appropriate alarm type using profile ringing type setting.
// -----------------------------------------------------------------------------
//
void CAlmAlarmPlayer::PlayCalendarAlarmL(TBool aIsRngTone)
{
    TRACE_ENTRY_POINT;
    if( iAlarmUtils->AlarmData().iRingType == EProfileRingingTypeBeepOnce )
    {
        PlayCalendarBeepL();
    }
    else if( iAlarmUtils->AlarmData().iRingType == EProfileRingingTypeSilent )
    {
        PlaySilentCalendarAlarmL();
    }
    else
    {
        if( aIsRngTone )
        {
            PlayCalendarAlarmToneL();
        }
        else // normal sound file
        {
            if( iSamplePlayer )
            {
                iSamplePlayer->Close();
                delete iSamplePlayer;
                iSamplePlayer = NULL;
            }
            iSamplePlayer = CMdaAudioPlayerUtility::NewFilePlayerL(
                iAlarmUtils->AlarmData().iAlarmTone,
                *this, 
                KAudioPriorityAlarm, 
                static_cast<TMdaPriorityPreference>( KAudioPrefCalendarAlarm ) );
        }
    }
    TRACE_EXIT_POINT;
}

// -----------------------------------------------------------------------------
// Play calendar alarm tone. (KRngMimeType files only)
// -----------------------------------------------------------------------------
//
void CAlmAlarmPlayer::PlayCalendarAlarmToneL(void)
{
    TRACE_ENTRY_POINT;
    if( iSequencePlayer )
    {
        delete iSequencePlayer;
        iSequencePlayer = NULL;
    }
    iSequencePlayer = CMdaAudioToneUtility::NewL( *this );

    iSequencePlayer->SetPriority( KAudioPriorityAlarm, static_cast<TMdaPriorityPreference>( KAudioPrefCalendarAlarm ) );

    iSequencePlayer->SetRepeats( iAlarmUtils->AlarmData().iRepeatValue, 
                                 TTimeIntervalMicroSeconds( KSoundInterval ) );

    SET_VOLUME( iSequencePlayer, 
                PlayerVolume( iSequencePlayer->MaxVolume(),
                              iAlarmUtils->AlarmData().iVolume ) )

    iSequencePlayer->SetVolumeRamp( TTimeIntervalMicroSeconds( iAlarmUtils->AlarmData().iVolumeRampTime ) );

    iSequencePlayer->PrepareToPlayFileSequence( iAlarmUtils->AlarmData().iAlarmTone );
    TRACE_EXIT_POINT;
}

// -----------------------------------------------------------------------------
// Play silent calendar alarm. (needed to for vibra)
// -----------------------------------------------------------------------------
//
void CAlmAlarmPlayer::PlaySilentCalendarAlarmL(void)
{
    TRACE_ENTRY_POINT;
    iBeepPlayer = CMdaAudioToneUtility::NewL( *this );

    SET_VOLUME( iBeepPlayer, 
                PlayerVolume( iBeepPlayer->MaxVolume(),
                              iAlarmUtils->AlarmData().iVolume ) )

    iBeepPlayer->SetPriority( KAudioPriorityAlarm, static_cast<TMdaPriorityPreference>( KAudioPrefCalendarAlarm ) );

    iBeepPlayer->PrepareToPlayDesSequence( KPhoneNoSoundSequence );
    TRACE_EXIT_POINT;
}

// -----------------------------------------------------------------------------
// Play beep alarm for calendar.
// -----------------------------------------------------------------------------
//
void CAlmAlarmPlayer::PlayCalendarBeepL(void)
{
    TRACE_ENTRY_POINT;
    iBeepPlayer = CMdaAudioToneUtility::NewL( *this );

    SET_VOLUME( iBeepPlayer, 
                PlayerVolume( iBeepPlayer->MaxVolume(),
                              iAlarmUtils->AlarmData().iVolume ) )

    iBeepPlayer->SetPriority( KAudioPriorityAlarm, static_cast<TMdaPriorityPreference>( KAudioPrefCalendarAlarm ) );

    iBeepPlayer->PrepareToPlayDesSequence( KPhoneBeepSequence );
    TRACE_EXIT_POINT;
}

// -----------------------------------------------------------------------------
// Play beep alarm for clock.
// -----------------------------------------------------------------------------
//
void CAlmAlarmPlayer::PlayClockBeepL(void)
{
    TRACE_ENTRY_POINT;
    iBeepPlayer = CMdaAudioToneUtility::NewL( *this );

    SET_VOLUME( iBeepPlayer, 
                PlayerVolume( iBeepPlayer->MaxVolume(),
                              iAlarmUtils->AlarmData().iVolume ) )

    iBeepPlayer->SetPriority( KAudioPriorityAlarm, static_cast<TMdaPriorityPreference>( KAudioPrefAlarmClock ) );

    iBeepPlayer->PrepareToPlayDesSequence( KPhoneBeepSequence );
    TRACE_EXIT_POINT;
}

// -----------------------------------------------------------------------------
// Play normal clock alarm.
// -----------------------------------------------------------------------------
//
void CAlmAlarmPlayer::PlayClockAlarmL(void)
{
    TRACE_ENTRY_POINT;
    if( iSamplePlayer )
    {
        iSamplePlayer->Close();
        delete iSamplePlayer;
        iSamplePlayer = NULL;
    }
    iSamplePlayer = CMdaAudioPlayerUtility::NewFilePlayerL(
        iAlarmUtils->AlarmData().iAlarmTone, 
        *this, 
        KAudioPriorityAlarm, 
        static_cast<TMdaPriorityPreference>( KAudioPrefAlarmClock ) );
    TRACE_EXIT_POINT;

}

// -----------------------------------------------------------------------------
// Play calendar alarm tone. (KRngMimeType files only)
// -----------------------------------------------------------------------------
//
void CAlmAlarmPlayer::PlayClockAlarmToneL(void)
{
    TRACE_ENTRY_POINT;
    if( iSequencePlayer )
    {
        delete iSequencePlayer;
        iSequencePlayer = NULL;
    }
    iSequencePlayer = CMdaAudioToneUtility::NewL( *this );

    iSequencePlayer->SetPriority( KAudioPriorityAlarm, static_cast<TMdaPriorityPreference>( KAudioPrefAlarmClock ) );

    iSequencePlayer->SetRepeats( iAlarmUtils->AlarmData().iRepeatValue, 
                                 TTimeIntervalMicroSeconds( KSoundInterval ) );

    SET_VOLUME( iSequencePlayer, 
                PlayerVolume( iSequencePlayer->MaxVolume(),
                              iAlarmUtils->AlarmData().iVolume ) )

    iSequencePlayer->SetVolumeRamp( TTimeIntervalMicroSeconds( iAlarmUtils->AlarmData().iVolumeRampTime ) );

    iSequencePlayer->PrepareToPlayFileSequence( iAlarmUtils->AlarmData().iAlarmTone );
    TRACE_EXIT_POINT;
}

// -----------------------------------------------------------------------------
// Check the file and alarm type and try to play the alarm.
// -----------------------------------------------------------------------------
//
void CAlmAlarmPlayer::PlayAlarmL()
{
    TRACE_ENTRY_POINT;
    if( iAlarmUtils->AlarmData().iAlarmTone.Length() )
    {
        const TBool isRngTone( iAlarmUtils->IsRngTone() );

        if( iAlarmUtils->IsClockAlarm() )
        {
            if( !isRngTone )
            {
                PlayClockAlarmL();
            }
            else
            {
                PlayClockAlarmToneL();
            }
        }
        else
        {
            PlayCalendarAlarmL( isRngTone );
        }
    }
    TRACE_EXIT_POINT;
}

// -----------------------------------------------------------------------------
// Common fallback functionality for prepare/play errors.
// -----------------------------------------------------------------------------
//
void CAlmAlarmPlayer::HandlePlayErrorL(TInt aError)
{
    TRACE_ENTRY_POINT;
    /**
    * No fallback for KErrUnderflow - alarm got replaced with the default beep.
    * Also, nothing to do if iBeepPlayer was already used.
    **/
    if( aError != KErrUnderflow && !iBeepPlayer )
    {
        // fallback to beep tone on OOM or if the default tone was already in use
        if( aError == KErrNoMemory || 
            iAlarmUtils->AlarmData().iAlarmTone == iAlarmUtils->AlarmData().iDefaultAlarmTone )
        {
            delete iSequencePlayer;
            iSequencePlayer = NULL;

            if( iSamplePlayer )
            {
                iSamplePlayer->Close();
            }
            delete iSamplePlayer;
            iSamplePlayer = NULL;

            // try playing the beep tone
            if( iAlarmUtils->IsClockAlarm() )
            {
                PlayClockBeepL();
            }
            else
            {
                PlayCalendarBeepL();
            }
        }
        else // retry using the default tone
        {
            iAlarmUtils->AlarmData().iAlarmTone = iAlarmUtils->AlarmData().iDefaultAlarmTone;
            PlayAlarmL();
        }
    }
    TRACE_EXIT_POINT;
}

// -----------------------------------------------------------------------------
// Set volume between zero and player's maximum volume
// -----------------------------------------------------------------------------
//
TInt CAlmAlarmPlayer::PlayerVolume(TInt aPlayerMaxVol, TInt aVol)
{
    TRACE_ENTRY_POINT;
    const TInt profileMaxVol( iAlarmUtils->MaxProfileVolume() );
    TInt vol( 0 ); // leave as 0 if using off tone
    if( !iAlarmUtils->IsOffTone() )
    {
        // calculate value between 0 and aPlayerMaxVolume
        vol = Max( 0, Min( aPlayerMaxVol / profileMaxVol * aVol, aPlayerMaxVol ) );
    }
    TRACE_EXIT_POINT;
    return vol;
}


// End of File