fmradio/fmradioengine/src/fmradiordsreceiverbase.cpp
changeset 0 f3d95d9c00ab
--- /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 );
+        }
+    }