--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/fmradio/fmradioengine/src/fmradiordsreceiverbase.cpp Tue Feb 02 00:17:10 2010 +0200
@@ -0,0 +1,524 @@
+/*
+* 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 );
+ }
+ }