diff -r cce62ebc198e -r 93c594350b9a fmradio/fmradioengine/src/fmradiordsreceiverbase.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fmradio/fmradioengine/src/fmradiordsreceiverbase.cpp Wed Sep 01 12:30:32 2010 +0100 @@ -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( 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& /*aFreqList*/ ) + { + } + +// --------------------------------------------------------------------------- +// CFMRadioRdsReceiverBase::MrroGetFreqByTAComplete +// --------------------------------------------------------------------------- +// +void CFMRadioRdsReceiverBase::MrroGetFreqByTAComplete( TInt /*aError*/, RArray& /*aFreqList*/ ) + { + } + +// --------------------------------------------------------------------------- +// CFMRadioRdsReceiverBase::MrroGetPSByPTYComplete +// --------------------------------------------------------------------------- +// +void CFMRadioRdsReceiverBase::MrroGetPSByPTYComplete( TInt /*aError*/, RArray& /*aPsList*/ ) + { + } + +// --------------------------------------------------------------------------- +// CFMRadioRdsReceiverBase::MrroGetPSByTAComplete +// --------------------------------------------------------------------------- +// +void CFMRadioRdsReceiverBase::MrroGetPSByTAComplete( TInt /*aError*/, RArray& /*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 ); + } + }