fmradio/fmradioengine/src/fmradiordsreceiverbase.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 02 Feb 2010 00:17:10 +0200
changeset 0 f3d95d9c00ab
permissions -rw-r--r--
Revision: 201003 Kit: 201005

/*
* Copyright (c) 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:  The RDS receiver implementation for FM Radio
*
*/


#include "fmradiordsreceiverbase.h"
#include "fmradiopubsub.h"
#include "fmradioengineradiosettings.h"

// The delay, in microseconds, after which RDS PS name is concidered static
const TInt KFMRadioStaticRdsPsNameDelay = 10000000; 

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

// ---------------------------------------------------------------------------
// CFMRadioRdsReceiverBase::CFMRadioRdsReceiverBase
// ---------------------------------------------------------------------------
//
CFMRadioRdsReceiverBase::CFMRadioRdsReceiverBase( TRadioSettings& aSettings ) : iSettings(aSettings)
    {
    }

// ---------------------------------------------------------------------------
// CFMRadioRdsReceiverBase::BaseConstructL
// ---------------------------------------------------------------------------
//
void CFMRadioRdsReceiverBase::BaseConstructL()
    {
    iPsName = HBufC::NewL( TRdsPSName().MaxLength() );
    iRadioText = HBufC::NewL( TRdsRadioText().MaxLength() );
    iPsNameTimer = CPeriodic::NewL( CActive::EPriorityStandard );
    }

// ---------------------------------------------------------------------------
// CFMRadioRdsReceiverBase::~CFMRadioRdsReceiverBase
// ---------------------------------------------------------------------------
//
CFMRadioRdsReceiverBase::~CFMRadioRdsReceiverBase()
    {
    iObservers.Close();
    delete iPsName;
    delete iRadioText;
    delete iPsNameTimer;
    
    iProgramWebUrl.Close();
    iArtistName.Close();
    iSongName.Close();
    iAlbumName.Close();
    }

// ---------------------------------------------------------------------------
// CFMRadioRdsReceiverBase::AddObserver
// ---------------------------------------------------------------------------
//
EXPORT_C void CFMRadioRdsReceiverBase::AddObserver( MFMRadioRdsObserver* aObserver )
    {
    TInt index = iObservers.FindInAddressOrder( aObserver );
    if( index == KErrNotFound )
        {
        iObservers.InsertInAddressOrder( aObserver );
        }
    }

// ---------------------------------------------------------------------------
// CFMRadioRdsReceiverBase::RemoveObserver
// ---------------------------------------------------------------------------
//
EXPORT_C void CFMRadioRdsReceiverBase::RemoveObserver( MFMRadioRdsObserver* aObserver )
    {
    TInt index = iObservers.FindInAddressOrder( aObserver );

    if( index >= 0 )
        {
        iObservers.Remove( index );
        }
    }

// ---------------------------------------------------------------------------
// CFMRadioRdsReceiverBase::AutomaticSwitchingEnabled
// ---------------------------------------------------------------------------
//
EXPORT_C TBool CFMRadioRdsReceiverBase::AutomaticSwitchingEnabled() const
    {
    return iAfEnabled;
    }

// ---------------------------------------------------------------------------
// CFMRadioRdsReceiverBase::ProgrammeService
// ---------------------------------------------------------------------------
//
EXPORT_C const TDesC& CFMRadioRdsReceiverBase::ProgrammeService() const
    {
    return *iPsName;
    }

// ---------------------------------------------------------------------------
// CFMRadioRdsReceiverBase::ProgrammeServiceNameType
// ---------------------------------------------------------------------------
//
EXPORT_C CFMRadioRdsReceiverBase::TFMRadioProgrammeSeviceType CFMRadioRdsReceiverBase::ProgrammeServiceNameType() const
    {
    return iPsNameType;
    }

// ---------------------------------------------------------------------------
// CFMRadioRdsReceiverBase::SignalAvailable
// ---------------------------------------------------------------------------
//
EXPORT_C TBool CFMRadioRdsReceiverBase::SignalAvailable() const
    {
    return iSignalAvailable;
    }

// ---------------------------------------------------------------------------
// CFMRadioRdsReceiverBase::RtPlusWebUrl
// ---------------------------------------------------------------------------
//
EXPORT_C const TDesC& CFMRadioRdsReceiverBase::RtPlusProgramUrl() const
    {
    return iProgramWebUrl;
    }

// ---------------------------------------------------------------------------
// CFMRadioRdsReceiverBase::RtPlusArtist
// ---------------------------------------------------------------------------
//
EXPORT_C const TDesC& CFMRadioRdsReceiverBase::RtPlusArtist() const
    {
    return iArtistName;
    }

// ---------------------------------------------------------------------------
// CFMRadioRdsReceiverBase::RtPlusAlbum
// ---------------------------------------------------------------------------
//
EXPORT_C const TDesC& CFMRadioRdsReceiverBase::RtPlusAlbum() const
    {
    return iAlbumName;
    }

// ---------------------------------------------------------------------------
// CFMRadioRdsReceiverBase::RtPlusSong
// ---------------------------------------------------------------------------
//
EXPORT_C const TDesC& CFMRadioRdsReceiverBase::RtPlusSong() const
    {
    return iSongName;
    }

// ---------------------------------------------------------------------------
// CFMRadioRdsReceiverBase::SetAutomaticSwitchingL
// ---------------------------------------------------------------------------
//
void CFMRadioRdsReceiverBase::SetAutomaticSwitchingL( TBool aEnable )
    {
    iAfEnabled = aEnable;
    for( TInt i = 0 ; i < iObservers.Count() ; i++ )
        {
        iObservers[i]->RdsAfSearchStateChange( iAfEnabled );
        }
    }

// ---------------------------------------------------------------------------
// CFMRadioRdsReceiverBase::ClearRdsInformation
// ---------------------------------------------------------------------------
//
void CFMRadioRdsReceiverBase::ClearRdsInformation()
    {
    TRdsPSName name;
    TRdsRadioText radioText;
    iPsNameTimer->Cancel();
    iPsNameType = EFMRadioPSNameStaticAssumed;
    MrroRdsDataPS( name );
    MrroRdsDataRT( radioText );
    iProgramWebUrl.Close();
    iArtistName.Close();
    iSongName.Close();
    iAlbumName.Close();
    MrroRdsEventSignalChange( EFalse );
    }

// ---------------------------------------------------------------------------
// CFMRadioRdsReceiverBase::StaticPsNameTimerCallback
// ---------------------------------------------------------------------------
//
TInt CFMRadioRdsReceiverBase::StaticPsNameTimerCallback( TAny* aSelf )
    {
    CFMRadioRdsReceiverBase* self = static_cast<CFMRadioRdsReceiverBase*>( aSelf );
    if( self )
        {
        self->iPsNameTimer->Cancel();
        if ( self->iPsNameType == EFMRadioPSNameStaticAssumed )
            {
            self->iPsNameType = EFMRadioPSNameStatic;
            for( TInt i = 0 ; i < self->iObservers.Count() ; i++ )
                {
                self->iObservers[i]->RdsDataPsNameIsStatic( ETrue );
                }
            }
        }
    return KErrNone;
    }

// ---------------------------------------------------------------------------
// CFMRadioRdsReceiverBase::HandleRdsDataRTplusL
// ---------------------------------------------------------------------------
//
void CFMRadioRdsReceiverBase::HandleRdsDataRTplusL( TRdsRTplusClass aRtPlusClass, TRdsRadioText& aRtPlusData )
    {
    TBool dataChanged = EFalse;
    switch (aRtPlusClass)
        {
        case ERTplusItemTitle:
            if ( aRtPlusData != iSongName )
                {
                dataChanged = ETrue;
                iSongName.Close();
                iSongName.CreateL( aRtPlusData );
                }
            break;
        case ERTplusItemArtist:
        case ERTplusItemBand:
            if ( aRtPlusData != iArtistName )
                {
                dataChanged = ETrue;
                iArtistName.Close();
                iArtistName.CreateL( aRtPlusData );
                }
            break;
        case ERTplusItemAlbum:
            if ( aRtPlusData != iAlbumName )
                {
                dataChanged = ETrue;
                iAlbumName.Close();
                iAlbumName.CreateL( aRtPlusData );
                }
            break;
        case ERTplusProgramHomepage:
            {
            if ( aRtPlusData != iProgramWebUrl )
                {
                dataChanged = ETrue;
                iProgramWebUrl.Close();
                iProgramWebUrl.CreateL( aRtPlusData );
                }
            break;
            }
        default:
            // Let uncached values go through
            dataChanged = ETrue;
            break;
        }
    
    if ( dataChanged )
        {
        for( TInt i = 0 ; i < iObservers.Count() ; i++ )
            {
            iObservers[i]->RdsDataRadioTextPlus( aRtPlusClass, aRtPlusData );
            }
        }
    }

// ---------------------------------------------------------------------------
// CFMRadioRdsReceiverBase::MrroStationSeekByPTYComplete
// ---------------------------------------------------------------------------
//
void CFMRadioRdsReceiverBase::MrroStationSeekByPTYComplete( TInt /*aError*/, TInt /*aFrequency*/ )
    {
    }

// ---------------------------------------------------------------------------
// CFMRadioRdsReceiverBase::MrroStationSeekByTAComplete
// ---------------------------------------------------------------------------
//
void CFMRadioRdsReceiverBase::MrroStationSeekByTAComplete( TInt /*aError*/, TInt /*aFrequency*/ )
    {
    }

// ---------------------------------------------------------------------------
// CFMRadioRdsReceiverBase::MrroStationSeekByTPComplete
// ---------------------------------------------------------------------------
//
void CFMRadioRdsReceiverBase::MrroStationSeekByTPComplete( TInt /*aError*/, TInt /*aFrequency*/ )
    {
    }

// ---------------------------------------------------------------------------
// CFMRadioRdsReceiverBase::MrroGetFreqByPTYComplete
// ---------------------------------------------------------------------------
//
void CFMRadioRdsReceiverBase::MrroGetFreqByPTYComplete( TInt /*aError*/, RArray<TInt>& /*aFreqList*/ )
    {
    }

// ---------------------------------------------------------------------------
// CFMRadioRdsReceiverBase::MrroGetFreqByTAComplete
// ---------------------------------------------------------------------------
//
void CFMRadioRdsReceiverBase::MrroGetFreqByTAComplete( TInt /*aError*/, RArray<TInt>& /*aFreqList*/ )
    {
    }

// ---------------------------------------------------------------------------
// CFMRadioRdsReceiverBase::MrroGetPSByPTYComplete
// ---------------------------------------------------------------------------
//
void CFMRadioRdsReceiverBase::MrroGetPSByPTYComplete( TInt /*aError*/, RArray<TRdsPSName>& /*aPsList*/ )
    {
    }

// ---------------------------------------------------------------------------
// CFMRadioRdsReceiverBase::MrroGetPSByTAComplete
// ---------------------------------------------------------------------------
//
void CFMRadioRdsReceiverBase::MrroGetPSByTAComplete( TInt /*aError*/, RArray<TRdsPSName>& /*aPsList*/ )
    {
    }

// ---------------------------------------------------------------------------
// CFMRadioRdsReceiverBase::MrroRdsDataPI
// ---------------------------------------------------------------------------
//
void CFMRadioRdsReceiverBase::MrroRdsDataPI( TInt /*aPi*/ )
    {
    }

// ---------------------------------------------------------------------------
// CFMRadioRdsReceiverBase::MrroRdsDataPTY
// ---------------------------------------------------------------------------
//
void CFMRadioRdsReceiverBase::MrroRdsDataPTY( TRdsProgrammeType /*aPty*/ )
    {
    }

// ---------------------------------------------------------------------------
// CFMRadioRdsReceiverBase::MrroRdsDataPS
// Notifies of the New Programme Service data
// ---------------------------------------------------------------------------
//
void CFMRadioRdsReceiverBase::MrroRdsDataPS( TRdsPSName& aPs )
    {
    TBool reportStaticState = EFalse;
    if ( iPsName->Length() && aPs.Length() )
        {
        if ( *iPsName != aPs && iPsNameTimer->IsActive() )
            {
            // PS existed and it changed, cancel the timer as it is not static name anymore
            iPsNameTimer->Cancel();
            iPsNameType = EFMRadioPSNameDynamic;
            reportStaticState = ETrue;
            }
        else
            {
            if ( iPsNameType == EFMRadioPSNameStaticAssumed && !iPsNameTimer->IsActive() )
                {
                // The timer should be reactivated in order to complete the determination
                iPsNameTimer->Start( KFMRadioStaticRdsPsNameDelay, 
                                     0, 
                                     TCallBack( CFMRadioRdsReceiverBase::StaticPsNameTimerCallback, this ) );
                }
            }
        }
    else if ( !iPsName->Length() && aPs.Length() )
        {
        // PS name is set for the first time, start the timer to see if it is a static one
        iPsNameTimer->Cancel();
        iPsNameTimer->Start( KFMRadioStaticRdsPsNameDelay, 
                             0, 
                             TCallBack( CFMRadioRdsReceiverBase::StaticPsNameTimerCallback, this ) );
        }
    else
        {
        // PS name is reset
        }
    
    iPsName->Des().Copy( aPs );
    
    if ( iPubSub )
        {
        TRAP_IGNORE( iPubSub->PublishRDSProgramServiceL( *iPsName ));
        }
 
    for( TInt i = 0 ; i < iObservers.Count() ; i++ )
        {
        iObservers[i]->RdsDataProgrammeService( *iPsName );
        if( reportStaticState )
            {
            iObservers[i]->RdsDataPsNameIsStatic( iPsNameType == EFMRadioPSNameStatic );
            }
        }
    }

// ---------------------------------------------------------------------------
// CFMRadioRdsReceiverBase::MrroRdsDataRT
// ---------------------------------------------------------------------------
//
void CFMRadioRdsReceiverBase::MrroRdsDataRT( TRdsRadioText& aRt )
    { 
    iRadioText->Des().Copy( aRt );
    for( TInt i = 0 ; i < iObservers.Count() ; i++ )
        {
        iObservers[i]->RdsDataRadioText( *iRadioText );
        }
    }

// ---------------------------------------------------------------------------
// CFMRadioRdsReceiverBase::MrroRdsDataCT
// ---------------------------------------------------------------------------
//
void CFMRadioRdsReceiverBase::MrroRdsDataCT( TDateTime& /*aCt*/ )
    {
    }

// ---------------------------------------------------------------------------
// CFMRadioRdsReceiverBase::MrroRdsDataTA
// ---------------------------------------------------------------------------
//
void CFMRadioRdsReceiverBase::MrroRdsDataTA( TBool /*aTaOn*/ )
    {
    }

// ---------------------------------------------------------------------------
// CFMRadioRdsReceiverBase::MrroRdsDataRTplus
// ---------------------------------------------------------------------------
//
void CFMRadioRdsReceiverBase::MrroRdsDataRTplus( TRdsRTplusClass aRtPlusClass, TRdsRadioText& aRtPlusData )
    {
    TRAP_IGNORE( HandleRdsDataRTplusL( aRtPlusClass, aRtPlusData ) )
    }

// ---------------------------------------------------------------------------
// CFMRadioRdsReceiverBase::MrroRdsSearchBeginAF
// Notifies of the start of Alternate Frequency search
// ---------------------------------------------------------------------------
//
void CFMRadioRdsReceiverBase::MrroRdsSearchBeginAF()
    {
    for( TInt i = 0 ; i < iObservers.Count() ; i++ )
        {
        iObservers[i]->RdsAfSearchBegin();
        }
    }

// ---------------------------------------------------------------------------
// CFMRadioRdsReceiverBase::MrroRdsSearchBeginAF
// Notifies of the end of Alternate Frequency search
// ---------------------------------------------------------------------------
//
void CFMRadioRdsReceiverBase::MrroRdsSearchEndAF( TInt aError, TInt aFrequency )
    {
    for( TInt i = 0 ; i < iObservers.Count() ; i++ )
        {
        // Radio utility uses Hz, UI uses kHz. It's ok to divide with 1000, possible lost fractions are useless.
        iObservers[i]->RdsAfSearchEnd( aFrequency / KFMRadioFreqMultiplier, aError );
        }
    }

// ---------------------------------------------------------------------------
// CFMRadioRdsReceiverBase::MrroRdsStationChangeTA
// ---------------------------------------------------------------------------
//
void CFMRadioRdsReceiverBase::MrroRdsStationChangeTA( TInt /*aFrequency*/ )
    {
    }

// ---------------------------------------------------------------------------
// CFMRadioRdsReceiverBase::MrroRdsEventAutomaticSwitchingChange
// ---------------------------------------------------------------------------
//
void CFMRadioRdsReceiverBase::MrroRdsEventAutomaticSwitchingChange( TBool /*aAuto*/ )
    {
    }

// ---------------------------------------------------------------------------
// CFMRadioRdsReceiverBase::MrroRdsEventAutomaticTrafficAnnouncement
// ---------------------------------------------------------------------------
//
void CFMRadioRdsReceiverBase::MrroRdsEventAutomaticTrafficAnnouncement( TBool /*aAuto*/ )
    {
    }

// ---------------------------------------------------------------------------
// CFMRadioRdsReceiverBase::MrroRdsEventSignalChange
// ---------------------------------------------------------------------------
//
void CFMRadioRdsReceiverBase::MrroRdsEventSignalChange( TBool aSignal )
    {
    if ( aSignal )
        {
        if ( iPsName->Length() )
            {
            if ( iPsNameType == EFMRadioPSNameStaticAssumed && !iPsNameTimer->IsActive() )
                {
                iPsNameTimer->Cancel();
                iPsNameTimer->Start( KFMRadioStaticRdsPsNameDelay, 
                                     0, 
                                     TCallBack( CFMRadioRdsReceiverBase::StaticPsNameTimerCallback, this ) );
                }
            }
        }
    else
        {
        // PS name type determination must be canceled on bad signal
        iPsNameTimer->Cancel();
        }
    iSignalAvailable = aSignal;
    for( TInt i = 0 ; i < iObservers.Count() ; i++ )
        {
        iObservers[i]->RdsAvailable( iSignalAvailable );
        }
    }