mmserv/radioutility/radioserver/Server/Src/RadioServer.cpp
changeset 0 71ca22bcf22a
child 3 4f62049db6ac
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mmserv/radioutility/radioserver/Server/Src/RadioServer.cpp	Tue Feb 02 01:08:46 2010 +0200
@@ -0,0 +1,3293 @@
+/*
+* Copyright (c) 2002-2004 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 is the main implementation of radio server.
+*
+*/
+
+
+
+// INCLUDE FILES
+#include    <mmf/common/mmfstandardcustomcommands.h>
+#include    <centralrepository.h>
+#include    <coreapplicationuissdkcrkeys.h>
+#include    <audiopreference.h>
+
+#include    "RadioServer.h"
+#include    "RadioServerSession.h"
+#include    "RadioServerShutdown.h"
+#include    "RadioServerSettings.h"
+#include    "RadioServerFmTuner.h"
+#include    "RadioDebug.h"
+
+// CONSTANTS
+const TInt KFMDefaultFreq           = 87500000; // 87.5 MHz
+const TInt KJapaneseFMDefaultFreq   = 76000000; // 76.0 MHz
+
+#ifndef RD_FM_RADIO_ENHANCEMENTS
+const TInt KEuroAmericaMin  =  87500000;
+const TInt KEuroAmericaMax  = 108000000;
+const TInt KJapanMin        =  76000000;
+const TInt KJapanMax        =  90000000;
+#endif //#ifdef RD_FM_RADIO_ENHANCEMENTS
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CRadioServer::CRadioServer
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CRadioServer::CRadioServer()
+    :   CServer2(CActive::EPriorityStandard),
+        iState(EStateStarted),
+        iSessionCount(0),
+        iSessionCountPrimary(0),
+        iShutdownTimer(NULL),
+        iSettings(NULL),
+        iTunerControlObserver(NULL),
+        iTunerControl(NULL),
+        iRdsControl(NULL),
+        iDevSound(NULL),
+        iRepository(NULL),
+        iCenRepNotifyHandler(NULL),
+        iAsyncRequestQue(_FOFF( TRadioMessageRequestData, iLink )),
+        iAsyncRequest(NULL),
+        iSyncRequestQue(_FOFF( TRadioMessageRequestData, iLink )),
+        iSyncRequest(NULL),
+        iMaxSigStrength(0),
+        iEnableTunerInOffline(EFalse),
+        iSquelch(EFalse),
+        iPreEmpted(EFalse)
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::ConstructL()
+    {
+    RADIO_RDEBUG(_L("[RADIO-SVR] ConstructL() - Start"));
+
+    StartL(KRadioServerName);
+
+    iDevSound = CMMFDevSound::NewL();
+    TMMFPrioritySettings prioritySettings;
+    prioritySettings.iPriority = (TInt)KAudioPriorityFMRadio;
+    prioritySettings.iPref = (TMdaPriorityPreference)KAudioPrefRadioAudioEvent;
+    iDevSound->SetPrioritySettings(prioritySettings);
+
+    // Sign up for offline mode status notification and get the latest status
+    iRepository = CRepository::NewL(KCRUidCoreApplicationUIs);
+    iCenRepNotifyHandler = CCenRepNotifyHandler::NewL(*this, *iRepository,
+            CCenRepNotifyHandler::EIntKey, KCoreAppUIsNetworkConnectionAllowed);
+    iCenRepNotifyHandler->StartListeningL();
+    TInt value;
+    TBool offlineMode = EFalse;
+    iRepository->Get(KCoreAppUIsNetworkConnectionAllowed, value);
+    if ( (TCoreAppUIsNetworkConnectionAllowed)value == ECoreAppUIsNetworkConnectionNotAllowed )
+        {
+        offlineMode = ETrue;
+        }
+
+    // Assume Antenna is connected. Otherwise, initialization will handle it anyways.
+    // After that, RadioServer gets the antenna status notification from the tuner.
+    TBool antennaStatus = ETrue;
+
+    // Max volume won't change, so just make the server remember it locally.
+    iMaxVolume = iDevSound->MaxVolume();
+    TInt volume = iDevSound->Volume();
+    TInt left, right;
+    iDevSound->GetPlayBalanceL(left, right);
+
+    iSettings = CRadioServerSettings::NewL();
+    iSettings->SetAntennaStatus(antennaStatus, EFalse);
+    iSettings->SetOfflineModeStatus(offlineMode, EFalse);
+    iSettings->SetVolume(volume, EFalse);
+    iSettings->SetBalance(left, right, EFalse);
+
+    // Initiate shut down unless we get client connections
+    iShutdownTimer = CRadioServerShutdown::NewL();
+    iShutdownTimer->Start();
+#ifdef RD_TSP_CLIENT_MAPPER
+    iMapper = CTspClientMapper::NewL();
+    iTspState = CTspClientMapper::ERegisteredClients;
+#endif // RD_TSP_CLIENT_MAPPER
+
+    RADIO_RDEBUG(_L("[RADIO-SVR] ConstructL() - End"));
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CRadioServer* CRadioServer::NewL()
+    {
+    RADIO_RDEBUG(_L("[RADIO-SVR] NewL"));
+    CRadioServer* self = new( ELeave ) CRadioServer;
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+// Destructor
+CRadioServer::~CRadioServer()
+    {
+    if ( iShutdownTimer )
+        {
+        iShutdownTimer->Cancel();
+        delete iShutdownTimer;
+        }
+    if ( iCenRepNotifyHandler )
+        {
+        iCenRepNotifyHandler->StopListening();
+        delete iCenRepNotifyHandler;
+        }
+    delete iRepository;
+
+    delete iDevSound;
+    delete iSettings;
+    delete iTunerControl;
+    delete iTunerControlObserver;
+    delete iAsyncRequest;
+
+    ClearQueue();
+    iRdsNotifyClientIdArray.Close();
+
+#ifdef RD_TSP_CLIENT_MAPPER
+    delete iMapper;
+    iClientPids.Close();
+#endif // RD_TSP_CLIENT_MAPPER
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::AddSession
+// This method increases the client session count, and cancels the shutdown timer.
+// The timer is reset once the last client has disconnected
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::AddSession()
+    {
+    if ( ++iSessionCount == 1 )
+        {
+        iShutdownTimer->Cancel();
+        iState = EStateStarted;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::DropSession
+// This method decrements the client session count, and if no clients are connected,
+// it initiates the shutdown timer.
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::DropSession()
+    {
+    if ( --iSessionCount == 0 )
+        {
+        RADIO_RDEBUG_INT(_L("[RADIO-SVR] DropSession() - Radio OFF. State[%d]"), iState);
+        switch ( iState )
+            {
+            case EStateStarted:
+            case EStateTunerOff:
+                // Shutting down normally.
+                iState = EStateStarted;
+                iMaxSigStrength = 0;
+                iEnableTunerInOffline = EFalse;
+                delete iTunerControl;
+                iTunerControl = NULL;
+                ClearQueue();
+                iShutdownTimer->Start();
+                break;
+            case EStateTunerOn:
+                iState = EStateShutdown;
+                iTunerControl->TunerOff();
+                break;
+            case EStatePlaying:
+                iState = EStateShutdown;
+                iDevSound->Stop();
+                iTunerControl->TunerOff();
+                break;
+            default:
+                break;
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ServiceRequestL
+// Main entry for Radio Server. If the cancel-request message is already outstanding,
+// just let it complete. Only allow for cancel if the message hasn't been initiated yet.
+// For all other requests, process the message if no other outstanding message exists.
+// Otherwise, queue the message. Execution order is guaranteed for all asynchronous
+// requests.
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::ServiceRequestL(
+    const RMessage2& aMessage )
+    {
+    TRadioServerRequest req;
+    TRadioMessageRequestData* data = NULL;
+#ifdef RD_TSP_CLIENT_MAPPER
+    iMessageTsp = aMessage;
+#endif // RD_TSP_CLIENT_MAPPER
+    switch( aMessage.Function() )
+        {
+        case ERadioServAddPrimaryClient:
+            iSessionCountPrimary++;
+            RegisterClientPidL(aMessage);
+            RADIO_RDEBUG_INT(_L("[RADIO-SVR] ServiceRequestL() prim=[%d]"), iSessionCountPrimary);
+            aMessage.Complete(KErrNone);
+            break;
+        case ERadioServRemovePrimaryClient:
+            aMessage.Complete(ProcessRemovePrimaryClientL(aMessage));
+            break;
+        case ERadioServGetTunerCapabilities:
+            aMessage.Complete(ProcessGetTunerCapabilities(aMessage));
+            break;
+        case ERadioServEnableTunerInOfflineMode:
+            aMessage.Complete(ProcessEnableTunerInOfflineMode(aMessage.Int1()));
+            break;
+        case ERadioServGetFrequencyRange:
+            aMessage.Complete(ProcessGetFrequencyRange(aMessage));
+            break;
+        case ERadioServGetFrequency:
+            aMessage.Complete(ProcessGetFrequency(aMessage));
+            break;
+        case ERadioServGetForceMonoReception:
+            aMessage.Complete(ProcessGetForceMonoReception(aMessage));
+            break;
+        case ERadioServSetSquelch:
+            aMessage.Complete(ProcessSetSquelch(aMessage.Int1()));
+            break;
+        case ERadioServGetSquelch:
+            aMessage.Complete(ProcessGetSquelch(aMessage));
+            break;
+        case ERadioServGetSignalStrength:
+        case ERadioServGetMaxSignalStrength:
+        case ERadioServGetStereoMode:
+        case ERadioServForceMonoReception:
+            // These requests are synchronous request from the client, however, the corresponding
+            // request to the tuner control is asynchronous. Therefore, these messages need to be
+            // serialized using a queue.
+            data = new (ELeave) TRadioMessageRequestData;
+            data->iType = (TRadioServerRequest) aMessage.Function();
+            data->iMessage = aMessage;
+            if ( iSyncRequest )
+                {
+                // Outstanding request exits; add it to the queue
+                iSyncRequestQue.AddLast(*data);
+                }
+            else
+                {
+                // No outstanding request; process the request
+                ProcessSyncRequest(data);
+                }
+            break;
+        case ERadioServGetPlayerState:
+            aMessage.Complete(ProcessGetPlayerState(aMessage));
+            break;
+        case ERadioServGetMaxVolume:
+            aMessage.Complete(ProcessGetMaxVolume(aMessage));
+            break;
+        case ERadioServSetVolume:
+            aMessage.Complete(ProcessSetVolume(aMessage.Int1()));
+            break;
+        case ERadioServGetVolume:
+            aMessage.Complete(ProcessGetVolume(aMessage));
+            break;
+        case ERadioServSetVolumeRamp:
+            aMessage.Complete(ProcessSetVolumeRamp(aMessage));
+            break;
+        case ERadioServSetMute:
+            aMessage.Complete(ProcessSetMute(aMessage.Int1()));
+            break;
+        case ERadioServGetMuteStatus:
+            aMessage.Complete(ProcessGetMuteStatus(aMessage));
+            break;
+        case ERadioServSetBalance:
+            aMessage.Complete(ProcessSetBalance(aMessage.Int1(), aMessage.Int2()));
+            break;
+        case ERadioServGetBalance:
+            aMessage.Complete(ProcessGetBalance(aMessage));
+            break;
+        case ERadioServRequestTunerControl:
+        case ERadioServSetFrequencyRange:
+        case ERadioServSetFrequency:
+        case ERadioServStationSeek:
+        case ERadioServPlay:
+        case ERadioServStop:
+        case ERadioServStationSeekByPTY:
+        case ERadioServStationSeekByTA:
+        case ERadioServStationSeekByTP:
+            // These requests are asynchronous request from the client. In order to guarantee the
+            // execution order these messages are serialized using a queue.
+            data = new (ELeave) TRadioMessageRequestData;
+            data->iType = (TRadioServerRequest) aMessage.Function();
+            data->iMessage = aMessage;
+            if ( iAsyncRequest )
+                {
+                // Outstanding request exits; add it to the queue
+                iAsyncRequestQue.AddLast(*data);
+                }
+            else
+                {
+                // No outstanding request; process the request
+                ProcessAsyncRequest(data);
+                }
+            break;
+        case ERadioServGetRdsCapabilities:
+            aMessage.Complete(ProcessGetRdsCapabilities(aMessage));
+            break;
+        case ERadioServGetRdsSignalStatus:
+            aMessage.Complete(ProcessGetRdsSignalStatus(aMessage));
+            break;
+        case ERadioServNotifyRdsDataChange:
+            aMessage.Complete(ProcessNotifyRdsDataChange(aMessage));
+            break;
+        case ERadioServCancelNotifyRdsDataChange:
+            aMessage.Complete(ProcessCancelNotifyRdsDataChange(aMessage));
+            break;
+        case ERadioServSetAutomaticSwitching:
+            aMessage.Complete(ProcessSetAutomaticSwitching(aMessage.Int1()));
+            break;
+        case ERadioServGetAutomaticSwitching:
+            aMessage.Complete(ProcessGetAutomaticSwitching(aMessage));
+            break;
+        case ERadioServCancelAFSearch:
+            aMessage.Complete(ProcessCancelAFSearch());
+            break;
+        case ERadioServGetProgrammeIdentification:
+            aMessage.Complete(ProcessGetProgrammeIdentification(aMessage));
+            break;
+        case ERadioServGetProgrammeType:
+            aMessage.Complete(ProcessGetProgrammeType(aMessage));
+            break;
+        case ERadioServGetProgrammeService:
+            aMessage.Complete(ProcessGetProgrammeService(aMessage));
+            break;
+        case ERadioServGetRadioText:
+            aMessage.Complete(ProcessGetRadioText(aMessage));
+            break;
+        case ERadioServGetClockTime:
+            aMessage.Complete(ProcessGetClockTime(aMessage));
+            break;
+        case ERadioServGetTrafficAnnouncementStatus:
+            aMessage.Complete(ProcessGetTrafficAnnouncementStatus(aMessage));
+            break;
+        case ERadioServGetTrafficProgrammeStatus:
+            aMessage.Complete(ProcessGetTrafficProgrammeStatus(aMessage));
+            break;
+        case ERadioServCancel:
+            req = (TRadioServerRequest) aMessage.Int1();
+            RADIO_RDEBUG_INT(_L("[RADIO-SVR] ServiceRequestL(): Cancel[%d]"), req);
+            switch ( req )
+                {
+                case ERadioServRequestTunerControl:
+                case ERadioServSetFrequencyRange:
+                case ERadioServSetFrequency:
+                    // If the message has already executed or is outstanding, just let it complete.
+                    // If not, remove from queue.
+                    RemoveFromQueue(iAsyncRequestQue, req);
+                    aMessage.Complete(KErrNone);
+                    break;
+                case ERadioServStationSeek:
+                case ERadioServStationSeekByPTY:
+                case ERadioServStationSeekByTA:
+                case ERadioServStationSeekByTP:
+                    // If the request is outstanding, attempt to cancel since it can take a while
+                    // to complete. Otherwise, just remove from the queue.
+                    if ( iAsyncRequest && ( (iAsyncRequest->iType == ERadioServStationSeek) ||
+                                            (iAsyncRequest->iType == ERadioServStationSeekByPTY) ||
+                                            (iAsyncRequest->iType == ERadioServStationSeekByTA) ||
+                                            (iAsyncRequest->iType == ERadioServStationSeekByTP) ) )
+                        {
+                        RADIO_RDEBUG(_L("[RADIO-SVR] ServiceRequestL() - Seek Outstanding"));
+                        if ( iAsyncRequest->iType == ERadioServStationSeek )
+                            {
+                            iTunerControl->CancelStationSeek();
+                            }
+                        else
+                            {
+                            iRdsControl->CancelRdsStationSeek();
+                            }
+                        // Disable squelching, if on
+                        if ( iSquelch )
+                            {
+                            // Restore the last volume
+                            iDevSound->SetVolume(iSettings->Volume());
+                            iSquelch = EFalse;
+                            }
+                        }
+                    else
+                        {
+                        RemoveFromQueue(iAsyncRequestQue, req);
+                        }
+                    aMessage.Complete(KErrNone);
+                    break;
+                default:
+                    RADIO_RDEBUG(_L("[RADIO-SVR] ServiceRequestL(): default !!!"));
+                    // Could be some custom command that we don't support.
+                    aMessage.Complete(KErrNotSupported);
+                }
+            break;
+        default:
+            RADIO_RDEBUG(_L("[RADIO-SVR] ServiceRequestL(): default!!!"));
+            // Could be some custom command that we don't support.
+            aMessage.Complete(KErrNotSupported);
+            break;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::NewSessionL
+// This method decrements the client session count, and if no clients are connected,
+// it initiates the shutdown timer.
+// -----------------------------------------------------------------------------
+//
+CSession2* CRadioServer::NewSessionL(
+    const TVersion& aVersion,
+    const RMessage2& /*aMessage*/ ) const
+    {
+    // Test if the version specifies a repository session
+    const TVersion version(KRadioServerVersionMajor,
+                           KRadioServerVersionMinor,
+                           KRadioServerVersionBuild);
+    if ( !User::QueryVersionSupported(aVersion, version) )
+        {
+        User::Leave(KErrNotSupported);
+        }
+
+    CRadioServerSession* session = CRadioServerSession::NewL(*((CRadioServer*)this));
+    return session;
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::TunerOnComplete (From MRadioServerFMTunerObserver)
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::TunerOnComplete(
+    TRadioServerError aError )
+    {
+    RADIO_RDEBUG_INT3(_L("[RADIO-SVR] TunerOnComplete(%d) State[%d] Trigger[%d]"), aError, iState, iTunerOnTrigger);
+    TFourCC radioFourCC;
+    switch ( iTunerOnTrigger )
+        {
+        case ETriggerTunerControl:
+            if ( aError == KErrNone )
+                {
+                TRsFrequencyRange range;
+                TInt minFreq, maxFreq;
+                if ( GetFrequencyRange(range, minFreq, maxFreq) == KErrNone )
+                    {
+                    RADIO_RDEBUG_INT3(_L("[RADIO-SVR] TunerOnComplete() - [%d, %d, %d]"), range, minFreq, maxFreq);
+                    iSettings->SetFrequencyRange( range, minFreq, maxFreq, EFalse );
+                    }
+                radioFourCC.Set(iTunerCaps.iEncoding);
+                TRAPD(err, iDevSound->InitializeL(*this, radioFourCC, EMMFStatePlaying));
+                if ( err != KErrNone )
+                    {
+                    RADIO_RDEBUG_INT(_L("[RADIO-SVR] TunerOnComplete() DevSound err=[%d]"), err);
+                    CompleteAsyncRequest(err);
+                    }
+                }
+            else
+                {
+                CompleteAsyncRequest(aError);
+                }
+            break;
+        case ETriggerSetFrequency:
+            if ( aError == KErrNone )
+                {
+                iState = EStateTunerOn;
+                }
+            CompleteAsyncRequest(aError);
+            break;
+        case ETriggerSetFrequencyRange:
+            if ( aError == KErrNone )
+                {
+                iState = EStateTunerOn;
+                TRsFrequencyRange range;
+                TInt minFreq, maxFreq;
+                if ( GetFrequencyRange(range, minFreq, maxFreq) == KErrNone )
+                    {
+                    RADIO_RDEBUG_INT3(_L("[RADIO-SVR] TunerOnComplete() - [%d, %d, %d]"), range, minFreq, maxFreq);
+                    iSettings->SetFrequencyRange( range, minFreq, maxFreq );
+                    }
+                }
+            CompleteAsyncRequest(aError);
+            break;
+        case ETriggerPlay:
+            if ( aError == KErrNone )
+                {
+                TRAPD(err, DoPlayL());
+                if ( err == KErrNone )
+                    {
+                    iState = EStatePlaying;
+                    iPreEmpted = EFalse;
+                    iSettings->SetRadioOn();
+                    SetTspTargetClient( ERsPlayerPlaying );
+                    }
+                CompleteAsyncRequest(err);
+                }
+            else
+                {
+                CompleteAsyncRequest(aError);
+                }
+            break;
+        case ETriggerAntenna:
+            if ( aError == KErrNone )
+                {
+                iState = EStateTunerOn;
+                // AK - begin: to cause publishing (CPHU-73YTQW)
+                iSettings->SetAntennaStatus(EFalse, EFalse);
+                // - end
+                iSettings->SetAntennaStatus(ETrue);
+                }
+            // else
+                // Unable to turn the tuner back on. It's possible that after TunerOn request
+                // has been sent that antenna has been disconnected or the offline mode has
+                // been enabled again. Just remain here...
+            break;
+        case ETriggerOffline:
+            if ( aError == KErrNone )
+                {
+                iState = EStateTunerOn;
+                iSettings->SetOfflineModeStatus(EFalse);
+                }
+            // else
+                // Unable to turn the tuner back on. It's possible that after TunerOn request
+                // has been sent that antenna has been disconnected or the offline mode has
+                // been enabled again. Just remain here...
+            break;
+        case ETriggerTransmitter:
+            if ( aError == KErrNone )
+                {
+                iState = EStateTunerOn;
+                iSettings->SetTransmitterStatus(EFalse);
+                }
+            // else
+                // Unable to turn the tuner back on. It's possible that after TunerOn request
+                // has been sent that antenna has been disconnected or the offline mode has
+                // been enabled again. Just remain here...
+            break;
+        default:
+            break;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::TunerOffComplete (From MRadioServerFMTunerObserver)
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::TunerOffComplete(
+    TRadioServerError aError )
+    {
+    RADIO_RDEBUG_INT2(_L("[RADIO-SVR] TunerOffComplete(%d) State[%d]"), aError, iState);
+    switch ( iState )
+        {
+        case EStateShutdown:
+            // We are shutting down normally. Called by destructor.
+            iState = EStateStarted;
+            iSettings->Reset();
+            iMaxSigStrength = 0;
+            iEnableTunerInOffline = EFalse;
+            delete iTunerControl;
+            iTunerControl = NULL;
+            ClearQueue();
+
+            if ( iSessionCount == 0 )
+                {
+                // Make sure a new session hasn't been started while TunerOff was being processed
+                iShutdownTimer->Start();
+                }
+            break;
+        case EStateTunerOff:
+            if ( iAsyncRequest && iAsyncRequest->iType == ERadioServSetFrequencyRange )
+                {
+                if ( aError == KErrNone )
+                    {
+                    RADIO_RDEBUG(_L("[RADIO-SVR] TunerOffComplete() - Tuner ON"));
+                    RecreateFmTunerControl();
+                    iTunerOnTrigger = ETriggerSetFrequencyRange;
+                    TFMRadioFrequencyRange freqRange = TunerControlFreqRange( iFreqRange );
+                    TInt freq = KFMDefaultFreq;
+                    if ( iFreqRange == ERsRangeFmJapan )
+                        {
+                        freq = KJapaneseFMDefaultFreq;
+                        }
+                    iTunerControl->TunerOn(freqRange, freq);
+                    }
+                else
+                    {
+                    CompleteAsyncRequest(aError);
+                    }
+                }
+            break;
+        default:
+            // should never happen
+            break;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::SetFrequencyRangeComplete (From MRadioServerFMTunerObserver)
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::SetFrequencyRangeComplete(
+    TRadioServerError aError )
+    {
+    RADIO_RDEBUG_INT2(_L("[RADIO-SVR] SetFrequencyRangeComplete(%d) State[%d]"), aError, iState);
+    if ( aError == KErrNone )
+        {
+        TRsFrequencyRange range;
+        TInt minFreq, maxFreq;
+        if ( GetFrequencyRange(range, minFreq, maxFreq) == KErrNone )
+            {
+            iSettings->SetFrequencyRange(range, minFreq, maxFreq);
+            }
+        else
+            {
+            iSettings->SetFrequencyRange(range, 0, 0);
+            }
+        }
+    CompleteAsyncRequest(aError);
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::SetFrequencyComplete (From MRadioServerFMTunerObserver)
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::SetFrequencyComplete(
+    TRadioServerError aError )
+    {
+    RADIO_RDEBUG_INT2(_L("[RADIO-SVR] SetFrequencyComplete(%d) State[%d]"), aError, iState);
+    if ( iAsyncRequest && iAsyncRequest->iType == ERadioServSetFrequency )
+        {
+        if ( aError == KErrNone )
+            {
+            iSettings->SetFrequency(iAsyncRequest->iMessage.Int1());
+            }
+        CompleteAsyncRequest(aError);
+        }
+    else
+        {
+        // Synchronization initiated from StationSeekComplete(). Ignore.
+        RADIO_RDEBUG(_L("[RADIO-SVR] SetFrequencyComplete()-SYNC done!"));
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::StationSeekComplete (From MRadioServerFMTunerObserver)
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::StationSeekComplete(
+    TRadioServerError aError,
+    TInt aFrequency )
+    {
+    RADIO_RDEBUG_INT3(_L("[RADIO-SVR] StationSeekComplete(%d, %d) State[%d]"), aError, aFrequency, iState);
+    if ( iAsyncRequest && ( (iAsyncRequest->iType == ERadioServStationSeek) ||
+                            (iAsyncRequest->iType == ERadioServStationSeekByPTY) ||
+                            (iAsyncRequest->iType == ERadioServStationSeekByTA) ||
+                            (iAsyncRequest->iType == ERadioServStationSeekByTP) ) )
+        {
+        // Disable squelching, if on
+        if ( iSquelch )
+            {
+            // Restore the last volume
+            iDevSound->SetVolume(iSettings->Volume());
+            iSquelch = EFalse;
+            }
+
+        if ( aError == KErrNone )
+            {
+            iSettings->SetFrequency(aFrequency);
+            TPckgBuf<TInt> p(aFrequency);
+            iAsyncRequest->iMessage.Write(2, p);
+            }
+        CompleteAsyncRequest(aError);
+        }
+    else
+        {
+        // Request was cancelled. Make sure the frequency is synchronized.
+        if ( iSettings->Frequency() != aFrequency )
+            {
+            RADIO_RDEBUG_INT(_L("[RADIO-SVR] StationSeekComplete()-SYNC to: Freq[%d]"), iSettings->Frequency());
+            iTunerControl->SetFrequency(iSettings->Frequency());
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::AudioModeComplete (From MRadioServerFMTunerObserver)
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::AudioModeComplete(
+    TRadioServerError aError,
+    TBool aStereo )
+    {
+    RADIO_RDEBUG_INT2(_L("[RADIO-SVR] AudioModeComplete(%d, %d)"), aError, aStereo);
+    if ( iSyncRequest && iSyncRequest->iType == ERadioServGetStereoMode )
+        {
+        if ( aError == KErrNone )
+            {
+            TPckgBuf<TBool> p(aStereo);
+            iSyncRequest->iMessage.Write(1, p);
+            }
+        CompleteSyncRequest(aError);
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::SetAudioModeComplete (From MRadioServerFMTunerObserver)
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::SetAudioModeComplete(
+    TRadioServerError aError )
+    {
+    RADIO_RDEBUG_INT(_L("[RADIO-SVR] AudioModeComplete(%d)"), aError);
+    TInt err = aError;
+    if ( iSyncRequest && iSyncRequest->iType == ERadioServForceMonoReception )
+        {
+        if ( err == KErrNone )
+            {
+            iSettings->SetForcedMonoStatus(iSyncRequest->iMessage.Int1());
+            if ( iState == EStatePlaying )
+                {
+                iDevSound->Stop();
+                TRAP(err, DoPlayL());
+                if ( err != KErrNone )
+                    {
+                    iSettings->SetRadioOff(err);
+                    SetTspTargetClient( ERsPlayerIdle );
+                    iState = EStateTunerOff;
+                    iTunerControl->TunerOff();
+                    RADIO_RDEBUG(_L("[RADIO-SVR] SetAudioModeComplete() - Tuner OFF"));
+                    }
+                }
+            }
+        CompleteSyncRequest(err);
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::SignalStrengthComplete (From MRadioServerFMTunerObserver)
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::SignalStrengthComplete(
+    TRadioServerError aError,
+    TInt aStrength )
+    {
+    RADIO_RDEBUG_INT2(_L("[RADIO-SVR] SignalStrengthComplete(%d, %d)"), aError, aStrength);
+    if ( iSyncRequest && iSyncRequest->iType == ERadioServGetSignalStrength )
+        {
+        if ( aError == KErrNone )
+            {
+            TPckgBuf<TInt> p(aStrength);
+            iSyncRequest->iMessage.Write(1, p);
+            }
+        CompleteSyncRequest(aError);
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::MaxSignalStrengthComplete (From MRadioServerFMTunerObserver)
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::MaxSignalStrengthComplete(
+    TRadioServerError aError,
+    TInt aMaxStrength )
+    {
+    RADIO_RDEBUG_INT2(_L("[RADIO-SVR] MaxSignalStrengthComplete(%d, %d)"), aError, aMaxStrength);
+    if ( iSyncRequest && iSyncRequest->iType == ERadioServGetMaxSignalStrength )
+        {
+        if ( aError == KErrNone )
+            {
+            iMaxSigStrength = aMaxStrength;
+            TPckgBuf<TInt> p(aMaxStrength);
+            iSyncRequest->iMessage.Write(1, p);
+            }
+        CompleteSyncRequest(aError);
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::SquelchComplete (From MRadioServerFMTunerObserver)
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::SquelchComplete(
+    TRadioServerError /*aError*/,
+    TBool /*aEnabled*/ )
+    {
+    // Not used.
+    // Squelch is handled internally in RadioServer
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::SetSquelchComplete (From MRadioServerFMTunerObserver)
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::SetSquelchComplete(
+    TRadioServerError /*aError*/ )
+    {
+    // Not used.
+    // Squelch is handled internally in RadioServer
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::BufferFilled (From MRadioServerFMTunerObserver)
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::BufferFilled(
+    TDes8& /*aBuffer*/ )
+    {
+    iDevSound->PlayData();
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::RadioEventAntennaStatusChange (From MRadioServerFMTunerObserver)
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::RadioEventAntennaStatusChange(
+    TBool aAttached )
+    {
+    RADIO_RDEBUG_INT2(_L("[RADIO-SVR] RadioEventAntennaStatusChange(%d) State[%d]"), aAttached, iState);
+    if ( iSettings->IsAntennaAttached() == aAttached )
+        {
+        // Do nothing since the state of the antenna hasn't changed.
+        RADIO_RDEBUG(_L("[RADIO-SVR] RadioEventAntennaStatusChange() - no change"));
+        return;
+        }
+
+    switch ( iState )
+        {
+        case EStateStarted:
+            // Just update the antenna status.
+            iSettings->SetAntennaStatus(aAttached);
+            RADIO_RDEBUG(_L("[RADIO-SVR] RadioEventAntennaStatusChange() - just antenna update"));
+            break;
+        case EStateTunerOn:
+        case EStatePlaying:
+            if ( iState == EStatePlaying )
+                {
+                iDevSound->Stop();
+                iSettings->SetRadioOff(KRadioServErrAntennaNotConnected);
+                SetTspTargetClient( ERsPlayerIdle );
+                }
+            // If we are receiving this at this state, it must be antenna detached
+            iSettings->SetAntennaStatus(EFalse);
+
+            // If station seek request is currently pending, complete the message since the
+            // adaptation will never complete this for us.
+            if ( iAsyncRequest && ( (iAsyncRequest->iType == ERadioServStationSeek) ||
+                                    (iAsyncRequest->iType == ERadioServStationSeekByPTY) ||
+                                    (iAsyncRequest->iType == ERadioServStationSeekByTA) ||
+                                    (iAsyncRequest->iType == ERadioServStationSeekByTP) ) )
+                {
+                RADIO_RDEBUG(_L("[RADIO-SVR] RadioEventAntennaStatusChange() - Seek Outstanding"));
+                if ( iAsyncRequest->iType == ERadioServStationSeek )
+                    {
+                    iTunerControl->CancelStationSeek();
+                    }
+                else
+                    {
+                    iRdsControl->CancelRdsStationSeek();
+                    }
+                // Disable squelching, if on
+                if ( iSquelch )
+                    {
+                    // Restore the last volume
+                    iDevSound->SetVolume(iSettings->Volume());
+                    iSquelch = EFalse;
+                    }
+                CompleteAsyncRequest(KRadioServErrAntennaNotConnected);
+                }
+
+            iState = EStateTunerOff;
+            iTunerControl->TunerOff();
+            RADIO_RDEBUG(_L("[RADIO-SVR] RadioEventAntennaStatusChange() - Tuner OFF"));
+            break;
+        case EStateTunerOff:
+            if ( aAttached )
+                {
+                if ( !iSettings->IsOfflineModeEnabled() && !iSettings->IsTransmitterActive() && !iPreEmpted )
+                    {
+                    // Don't notify the client about the antenna status change yet.
+                    // Notify once the Tuner is turned ON.
+                    RADIO_RDEBUG(_L("[RADIO-SVR] RadioEventAntennaStatusChange() - Tuner ON"));
+                    // AK - begin: need to set this status because recreating tuner will trigger another
+                    // RadioEventAntennaStatusChange. (CPHU-73YTQW)
+                    iSettings->SetAntennaStatus(ETrue, EFalse);
+                    RecreateFmTunerControl();
+                    // - end
+                    iTunerOnTrigger = ETriggerAntenna;
+                    TFMRadioFrequencyRange freqRange = TunerControlFreqRange( iSettings->FrequencyRange() );
+                    iTunerControl->TunerOn(freqRange, iSettings->Frequency());
+                    }
+                else
+                    {
+                    // Can't turn the tuner ON yet. Just update the antenna status.
+                    RADIO_RDEBUG(_L("[RADIO-SVR] RadioEventAntennaStatusChange() - Wait"));
+                    iSettings->SetAntennaStatus(ETrue);
+                    }
+                }
+            else
+                {
+                // Just update the antenna status.
+                iSettings->SetAntennaStatus(EFalse);
+                }
+            break;
+        default :
+            break;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::RadioEventTunerControlChange (From MRadioServerFMTunerObserver)
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::RadioEventTunerControlChange(
+    TRadioServerError aError )
+    {
+    RADIO_RDEBUG_INT2(_L("[RADIO-SVR] RadioEventTunerControlChange(%d) State[%d]"), aError, iState);
+    switch ( iState )
+        {
+        case EStateStarted:
+            // Just update the transmitter status.
+            if ( aError == KErrNone )
+                {
+                iSettings->SetTransmitterStatus(EFalse);
+                }
+            else if ( aError == KRadioServErrFmTransmitterActive )
+                {
+                iSettings->SetTransmitterStatus(ETrue);
+                }
+            break;
+        case EStateTunerOn:
+        case EStatePlaying:
+            if ( iState == EStatePlaying )
+                {
+                iDevSound->Stop();
+                iSettings->SetRadioOff(aError);
+                SetTspTargetClient( ERsPlayerIdle );
+                }
+            // Tuner was forced off due to hardware conflict
+            if ( aError == KRadioServErrFmTransmitterActive )
+                {
+                iSettings->SetTransmitterStatus(ETrue);
+                }
+            iState = EStateTunerOff;
+            iTunerControl->TunerOff();
+            RADIO_RDEBUG(_L("[RADIO-SVR] RadioEventTunerControlChange() - Tuner OFF"));
+            break;
+        case EStateTunerOff:
+            if ( aError == KErrNone )
+                {
+                if ( iSettings->IsAntennaAttached() && !iSettings->IsOfflineModeEnabled() && !iPreEmpted )
+                    {
+                    // Don't notify the client about the transmitter status change yet.
+                    // Notify once the Tuner is turned ON.
+                    RADIO_RDEBUG(_L("[RADIO-SVR] RadioEventTunerControlChange() - Tuner ON"));
+                    RecreateFmTunerControl();
+                    iTunerOnTrigger = ETriggerTransmitter;
+                    TFMRadioFrequencyRange freqRange = TunerControlFreqRange( iSettings->FrequencyRange() );
+                    iTunerControl->TunerOn(freqRange, iSettings->Frequency());
+                    }
+                else
+                    {
+                    // Can't turn the tuner ON yet. Just update the transmitter status.
+                    iSettings->SetTransmitterStatus(EFalse);
+                    }
+                }
+            else if ( aError == KRadioServErrFmTransmitterActive )
+                {
+                // Just update the transmitter status.
+                iSettings->SetTransmitterStatus(ETrue);
+                }
+            break;
+        default :
+            break;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::StationSeekByPTYComplete (From MRadioServerFMTunerObserver)
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::StationSeekByPTYComplete(
+    TRadioServerError aError,
+    TInt aFrequency )
+    {
+    StationSeekComplete(aError,aFrequency);
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::StationSeekByTAComplete (From MRadioServerFMTunerObserver)
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::StationSeekByTAComplete(
+    TRadioServerError aError,
+    TInt aFrequency )
+    {
+    StationSeekComplete(aError,aFrequency);
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::StationSeekByTPComplete (From MRadioServerFMTunerObserver)
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::StationSeekByTPComplete(
+    TRadioServerError aError,
+    TInt aFrequency )
+    {
+    StationSeekComplete(aError,aFrequency);
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::RdsDataPI (From MRadioServerFMTunerObserver)
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::RdsDataPI(
+    TInt aPi )
+    {
+    RADIO_RDEBUG_INT(_L("[RADIO-SVR] RdsDataPI(%d)"), aPi);
+    iSettings->SetProgrammeIdentification(aPi);
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::RdsDataPTY (From MRadioServerFMTunerObserver)
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::RdsDataPTY(
+    TRdsProgrammeType aPty )
+    {
+    RADIO_RDEBUG_INT(_L("[RADIO-SVR] RdsDataPTY(%d)"), aPty);
+    iSettings->SetProgrammeType(aPty);
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::RdsDataPS (From MRadioServerFMTunerObserver)
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::RdsDataPS(
+    TRdsPSName& aPs )
+    {
+    RADIO_RDEBUG_INT(_L("[RADIO-SVR] RdsDataPTY(%S)"), &aPs);
+    iSettings->SetProgrammeService(aPs);
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::RdsDataRT (From MRadioServerFMTunerObserver)
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::RdsDataRT(
+    TRdsRadioText& aRt,
+    RArray<TRdsRTplusTag>& aRTplusTags )
+    {
+    RADIO_RDEBUG_INT(_L("[RADIO-SVR] RdsDataRT(%S)"), &aRt);
+    TRdsRTplusTag tag1;
+    TRdsRTplusTag tag2;
+    TRdsRadioText rtPlusObject1;
+    TRdsRadioText rtPlusObject2;
+    TRdsRadioText aRtCopy;
+    
+    aRtCopy.Copy( aRt );
+    iSettings->SetRadioText( aRt );
+
+    if( aRTplusTags.Count() > 0 )
+        {
+        // tags present, extract objects pointed by the tags
+        RADIO_RDEBUG(_L("[RADIO-SVR] RT+ tags found, extract objects and pass them through"));
+        tag1 = aRTplusTags[ 0 ];
+        tag2 = aRTplusTags[ 1 ];
+        
+        if( tag1.iContentType == ERTplusItemDummy )
+            {
+            RADIO_RDEBUG(_L("[RADIO-SVR] Tag1 dummy, skipped!"));
+            }
+        else
+            {
+            // extract object from RadioText payload pointed by received tag information
+            TInt length = tag1.iLength + 1;
+            TInt start = tag1.iStart;
+            TInt rtLength = aRtCopy.Length();
+
+            if( start > rtLength )
+                {
+                start = rtLength;
+                RADIO_RDEBUG(_L("[RADIO-SVR] Tag1 start marker adjusted"));
+                }
+            
+            if( length + start > rtLength )
+                {
+                //Make sure we don't try to copy too much, in case of erroneous length indicators
+                length = rtLength - start;
+                RADIO_RDEBUG(_L("[RADIO-SVR] Tag1 length marker adjusted"));
+                }
+            rtPlusObject1 = aRtCopy.Mid( start, length );
+            }
+        
+        if( tag2.iContentType == ERTplusItemDummy )
+            {
+            RADIO_RDEBUG(_L("[RADIO-SVR] Tag2 dummy, skipped!"));
+            }
+        else
+            {
+            // extract object from RadioText payload pointed by received tag information
+            TInt length = tag2.iLength + 1;
+            TInt start = tag2.iStart;
+            TInt rtLength = aRtCopy.Length();
+
+            if( start > rtLength )
+                {
+                start = rtLength;
+                RADIO_RDEBUG(_L("[RADIO-SVR] Tag2 start marker adjusted"));
+                }
+            
+            if( length + start > rtLength )
+                {
+                //Make sure we don't try to copy too much, in case of erroneous length indicators
+                length = rtLength - start;
+                RADIO_RDEBUG(_L("[RADIO-SVR] Tag2 length marker adjusted"));
+                }
+            rtPlusObject2 = aRtCopy.Mid( start, length );
+            }
+        RADIO_RDEBUG(_L("[RADIO-SVR] Passing RT+ objects"));
+        iSettings->SetRadioTextPlusObjects( rtPlusObject1, tag1.iContentType,
+                rtPlusObject2, tag2.iContentType );
+        }
+    aRTplusTags.Reset();
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::RdsDataCT (From MRadioServerFMTunerObserver)
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::RdsDataCT(
+    TDateTime& aCt )
+    {
+    RADIO_RDEBUG(_L("[RADIO-SVR] RdsDataCT()"));
+    iSettings->SetClockTime(aCt);
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::RdsDataTA (From MRadioServerFMTunerObserver)
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::RdsDataTA(
+    TBool aTaOn )
+    {
+    RADIO_RDEBUG_INT(_L("[RADIO-SVR] RdsDataTA(%d)"), aTaOn);
+    iSettings->SetTrafficAnnouncementStatus(aTaOn);
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::RdsSearchBeginAF (From MRadioServerFMTunerObserver)
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::RdsSearchBeginAF()
+    {
+    RADIO_RDEBUG(_L("[RADIO-SVR] RdsSearchBeginAF()"));
+    iSettings->SetRdsBeginAF();
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::RdsSearchEndAF (From MRadioServerFMTunerObserver)
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::RdsSearchEndAF(
+    TRadioServerError aError,
+    TInt aFrequency )
+    {
+    RADIO_RDEBUG_INT2(_L("[RADIO-SVR] RdsSearchEndAF(%d, %d)"), aError, aFrequency);
+    iSettings->SetRdsEndAF(aError, aFrequency);
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::RdsEventSignalChange (From MRadioServerFMTunerObserver)
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::RdsEventSignalChange(
+    TBool aSignal )
+    {
+    iSettings->SetRdsSignalChange(aSignal);
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::InitializeComplete (From MDevSoundObserver)
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::InitializeComplete(
+    TInt aError )
+    {
+    RADIO_RDEBUG_INT2(_L("[RADIO-SVR] InitializeComplete(%d) State[%d]"), aError, iState);
+    if ( aError == KErrNone )
+        {
+        TMMFCapabilities devSoundCaps = iDevSound->Capabilities();
+        RADIO_RDEBUG_INT3(_L("[RADIO-SVR] InitializeComplete - DevSound(%d, %d, %d)"), devSoundCaps.iRate, devSoundCaps.iEncoding, devSoundCaps.iChannels);
+
+        TUint tunerRate = iTunerCaps.iSampleRate;
+        TUint devSoundRate = devSoundCaps.iRate;
+        // Pick the highest sample rate possible
+        if ( (tunerRate & EFMRadioSampleRate96000Hz) && (devSoundRate & EMMFSampleRate96000Hz) )
+            {
+            iDevSoundConfig.iRate = EMMFSampleRate96000Hz;
+            }
+        else if ( (tunerRate == EFMRadioSampleRate88200Hz) && (devSoundRate & EMMFSampleRate88200Hz) )
+            {
+            iDevSoundConfig.iRate = EMMFSampleRate88200Hz;
+            }
+        else if ( (tunerRate == EFMRadioSampleRate64000Hz) && (devSoundRate & EMMFSampleRate64000Hz) )
+            {
+            iDevSoundConfig.iRate = EMMFSampleRate64000Hz;
+            }
+        else if ( (tunerRate == EFMRadioSampleRate48000Hz) && (devSoundRate & EMMFSampleRate48000Hz) )
+            {
+            iDevSoundConfig.iRate = EMMFSampleRate48000Hz;
+            }
+        else if ( (tunerRate == EFMRadioSampleRate44100Hz) && (devSoundRate & EMMFSampleRate44100Hz) )
+            {
+            iDevSoundConfig.iRate = EMMFSampleRate44100Hz;
+            }
+        else if ( (tunerRate == EFMRadioSampleRate32000Hz) && (devSoundRate & EMMFSampleRate32000Hz) )
+            {
+            iDevSoundConfig.iRate = EMMFSampleRate32000Hz;
+            }
+        else if ( (tunerRate == EFMRadioSampleRate24000Hz) && (devSoundRate & EMMFSampleRate24000Hz) )
+            {
+            iDevSoundConfig.iRate = EMMFSampleRate24000Hz;
+            }
+        else if ( (tunerRate == EFMRadioSampleRate22050Hz) && (devSoundRate & EMMFSampleRate22050Hz) )
+            {
+            iDevSoundConfig.iRate = EMMFSampleRate22050Hz;
+            }
+        else if ( (tunerRate == EFMRadioSampleRate16000Hz) && (devSoundRate & EMMFSampleRate16000Hz) )
+            {
+            iDevSoundConfig.iRate = EMMFSampleRate16000Hz;
+            }
+        else if ( (tunerRate == EFMRadioSampleRate12000Hz) && (devSoundRate & EMMFSampleRate12000Hz) )
+            {
+            iDevSoundConfig.iRate = EMMFSampleRate12000Hz;
+            }
+        else if ( (tunerRate == EFMRadioSampleRate11025Hz) && (devSoundRate & EMMFSampleRate11025Hz) )
+            {
+            iDevSoundConfig.iRate = EMMFSampleRate11025Hz;
+            }
+        else if ( (tunerRate == EFMRadioSampleRate8000Hz) && (devSoundRate & EMMFSampleRate8000Hz) )
+            {
+            iDevSoundConfig.iRate = EMMFSampleRate8000Hz;
+            }
+        else
+            {
+            // Nothing matched
+            RADIO_RDEBUG(_L("[RADIO-SVR] InitializeComplete() - incompatible sample rate"));
+            CompleteAsyncRequest(KRadioServErrHardwareFaulty);
+            return;
+            }
+
+        TUint tunerChan = iTunerCaps.iChannels;
+        TUint devSoundChan = devSoundCaps.iChannels;
+        if ( ((tunerChan & EFMRadioAudioMono) && (devSoundChan & EMMFMono)) &&
+             ((tunerChan & EFMRadioAudioStereo) && (devSoundChan & EMMFStereo)))
+            {
+            iChannels = EChannelBoth;
+            }
+        else if ( (tunerChan & EFMRadioAudioMono) && (devSoundChan & EMMFMono) )
+            {
+            iChannels = EChannelMono;
+            iSettings->SetForcedMonoStatus(ETrue, EFalse);
+            }
+        else if ( (tunerChan & EFMRadioAudioStereo) && (devSoundChan & EMMFStereo) )
+            {
+            iChannels = EChannelStereo;
+            }
+        else
+            {
+            // Nothing matched
+            RADIO_RDEBUG(_L("[RADIO-SVR] InitializeComplete() - incompatible channels"));
+            CompleteAsyncRequest(KRadioServErrHardwareFaulty);
+            return;
+            }
+        iState = EStateTunerOn;
+        CompleteAsyncRequest(KErrNone);
+        }
+    else
+        {
+        CompleteAsyncRequest(aError);
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ToneFinished (From MDevSoundObserver)
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::ToneFinished(
+    TInt /*aError*/ )
+    {
+    // Not used
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::BufferToBeFilled (From MDevSoundObserver)
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::BufferToBeFilled(
+    CMMFBuffer* aBuffer )
+    {
+    RADIO_RDEBUG(_L("[RADIO-SVR] BufferToBeFilled()"));
+    iTunerControl->BufferToBeFilled(STATIC_CAST(CMMFDataBuffer*, aBuffer)->Data());
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::PlayError (From MDevSoundObserver)
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::PlayError(
+    TInt aError )
+    {
+    RADIO_RDEBUG_INT2(_L("[RADIO-SVR] PlayError(%d) State[%d]"), aError, iState);
+    if ( iState == EStatePlaying )
+        {
+        // If station seek request is currently pending, complete the message since the
+        // adaptation will never complete this for us.
+        if ( iAsyncRequest && ( (iAsyncRequest->iType == ERadioServStationSeek) ||
+                                (iAsyncRequest->iType == ERadioServStationSeekByPTY) ||
+                                (iAsyncRequest->iType == ERadioServStationSeekByTA) ||
+                                (iAsyncRequest->iType == ERadioServStationSeekByTP) ) )
+            {
+            RADIO_RDEBUG(_L("[RADIO-SVR] PlayError() - Seek Outstanding"));
+            if ( iAsyncRequest->iType == ERadioServStationSeek )
+                {
+                iTunerControl->CancelStationSeek();
+                }
+            else
+                {
+                iRdsControl->CancelRdsStationSeek();
+                }
+            // Disable squelching, if on
+            if ( iSquelch )
+                {
+                // Restore the last volume
+                iDevSound->SetVolume(iSettings->Volume());
+                iSquelch = EFalse;
+                }
+            CompleteAsyncRequest(KRadioServErrTuning);
+            }
+
+        // We are being pre-empted by another application with higher priority.
+        // Turn the tuner off also to prevent interference + power saving.
+        iState = EStateTunerOff;
+        iPreEmpted = ETrue;
+        iSettings->SetRadioOff(aError);
+        iTunerControl->TunerOff();
+        SetTspTargetClient( ERsPlayerIdle );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::BufferToBeEmptied (From MDevSoundObserver)
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::BufferToBeEmptied(
+    CMMFBuffer* /*aBuffer*/ )
+    {
+    // Not used
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::RecordError (From MDevSoundObserver)
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::RecordError(
+    TInt /*aError*/ )
+    {
+    // Not used
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ConvertError (From MDevSoundObserver)
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::ConvertError(
+    TInt /*aError*/ )
+    {
+    // Not used
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::DeviceMessage (From MDevSoundObserver)
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::DeviceMessage(
+    TUid /*aMessageType*/,
+    const TDesC8& /*aMsg*/ )
+    {
+    // Not used
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::SendEventToClient (From MDevSoundObserver)
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::SendEventToClient(
+    const TMMFEvent& /*aEvent*/ )
+    {
+    // Attempt to acquire sound device is rejected by audio policy server.
+    RADIO_RDEBUG_INT(_L("[RADIO-SVR] BufferToBeFilled() State[%d]"), iState);
+    iState = EStateTunerOn;
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::HandleNotifyInt (From MCenRepNotifyHandlerCallback)
+// Notification from Central Repository indicating change in device's offline mode.
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::HandleNotifyInt(
+    TUint32 aId,
+    TInt /*aNewValue*/ )
+    {
+    RADIO_RDEBUG(_L("[RADIO-SVR] HandleNotifyInt()"));
+    // Start listening immediately before analyzing the notification to ensure that we
+    // don't miss further updates.
+    TRAPD(err, iCenRepNotifyHandler->StartListeningL());
+    if ( err != KErrNone )
+        {
+        User::Panic(_L("RadioServer-CR"), err );
+        }
+    if ( aId != KCoreAppUIsNetworkConnectionAllowed )
+        {
+        return;
+        }
+    TInt value;
+    iRepository->Get(KCoreAppUIsNetworkConnectionAllowed, value);
+
+    TBool offlineEnabled = EFalse;
+    if ( (TCoreAppUIsNetworkConnectionAllowed)value == ECoreAppUIsNetworkConnectionNotAllowed )
+        {
+        offlineEnabled = ETrue;
+        }
+
+    if ( iSettings->IsOfflineModeEnabled() == offlineEnabled )
+        {
+        // Do nothing since the offline status hasn't changed.
+        return;
+        }
+
+    switch ( iState )
+        {
+        case EStateStarted:
+            // Just update the offline mode status.
+            iSettings->SetOfflineModeStatus(offlineEnabled);
+            break;
+        case EStateTunerOn:
+        case EStatePlaying:
+            iSettings->SetOfflineModeStatus(offlineEnabled);
+            if ( !AllowRadioInOfflineMode() )
+                {
+                if ( iState == EStatePlaying )
+                    {
+                    iDevSound->Stop();
+                    iSettings->SetRadioOff(KRadioServErrOfflineMode);
+                    SetTspTargetClient( ERsPlayerIdle );
+                    }
+
+                // If station seek request is currently pending, complete the message since the
+                // adaptation will never complete this for us.
+                if ( iAsyncRequest && ( (iAsyncRequest->iType == ERadioServStationSeek) ||
+                                        (iAsyncRequest->iType == ERadioServStationSeekByPTY) ||
+                                        (iAsyncRequest->iType == ERadioServStationSeekByTA) ||
+                                        (iAsyncRequest->iType == ERadioServStationSeekByTP) ) )
+                    {
+                    RADIO_RDEBUG(_L("[RADIO-SVR] HandleNotifyInt() - Seek Outstanding"));
+                    if ( iAsyncRequest->iType == ERadioServStationSeek )
+                        {
+                        iTunerControl->CancelStationSeek();
+                        }
+                    else
+                        {
+                        iRdsControl->CancelRdsStationSeek();
+                        }
+                    // Disable squelching, if on
+                    if ( iSquelch )
+                        {
+                        // Restore the last volume
+                        iDevSound->SetVolume(iSettings->Volume());
+                        iSquelch = EFalse;
+                        }
+                    CompleteAsyncRequest(KRadioServErrOfflineMode);
+                    }
+
+                iState = EStateTunerOff;
+                iTunerControl->TunerOff();
+                RADIO_RDEBUG(_L("[RADIO-SVR] HandleNotifyInt() - Tuner OFF"));
+                }
+            break;
+        case EStateTunerOff:
+            if ( offlineEnabled )
+                {
+                // Just update the offline mode status.
+                iSettings->SetOfflineModeStatus(ETrue);
+                }
+            else
+                {
+                if ( iSettings->IsAntennaAttached() && !iSettings->IsTransmitterActive() && !iPreEmpted )
+                    {
+                    // Don't notify the client about the offline mode status change yet.
+                    // Notify once the Tuner is turned ON.
+                    RADIO_RDEBUG(_L("[RADIO-SVR] HandleNotifyInt() - Tuner ON"));
+                    RecreateFmTunerControl();
+                    iTunerOnTrigger = ETriggerOffline;
+                    TFMRadioFrequencyRange freqRange = TunerControlFreqRange( iSettings->FrequencyRange() );
+                    iTunerControl->TunerOn(freqRange, iSettings->Frequency());
+                    }
+                else
+                    {
+                    // Can't turn the tuner ON yet. Just update the offline mode status.
+                    iSettings->SetOfflineModeStatus(EFalse);
+                    }
+                }
+            break;
+        default :
+            break;
+        }
+    }
+
+/***********************************************************
+ *     Internal Functions Begin                            *
+ ***********************************************************/
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessAsyncRequest
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::ProcessAsyncRequest(
+    TRadioMessageRequestData* aRequest )
+    {
+    // Set the current outstanding request
+    iAsyncRequest = aRequest;
+    switch( aRequest->iType )
+        {
+        case ERadioServRequestTunerControl:
+            ProcessRequestTunerControl((TRsTuner)aRequest->iMessage.Int1());
+            break;
+        case ERadioServSetFrequencyRange:
+            ProcessSetFrequencyRange((TRsFrequencyRange)aRequest->iMessage.Int1());
+            break;
+        case ERadioServSetFrequency:
+            ProcessSetFrequency(aRequest->iMessage.Int1());
+            break;
+        case ERadioServStationSeek:
+            ProcessStationSeek(aRequest->iMessage.Int1());
+            break;
+        case ERadioServPlay:
+            ProcessPlay();
+            break;
+        case ERadioServStop:
+            ProcessStop(aRequest->iMessage.Int1());
+            break;
+        case ERadioServStationSeekByPTY:
+            ProcessStationSeekByPTY(aRequest->iMessage.Int1(), aRequest->iMessage.Int2());
+            break;
+        case ERadioServStationSeekByTA:
+            ProcessStationSeekByTA(aRequest->iMessage.Int1());
+            break;
+        case ERadioServStationSeekByTP:
+            ProcessStationSeekByTP(aRequest->iMessage.Int1());
+            break;
+        default:
+            break;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessRequestTunerControl
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::ProcessRequestTunerControl(
+    TRsTuner aTuner )
+    {
+    RADIO_RDEBUG_INT2(_L("[RADIO-SVR] ProcessRequestTunerControl(%d) State[%d]"), aTuner, iState);
+    if ( aTuner != ERsTunerFm )
+        {
+        // Only FM is supported at this point
+        CompleteAsyncRequest(KErrNotSupported);
+        return;
+        }
+
+    if ( iState != EStateStarted )
+        {
+        CompleteAsyncRequest(KErrAlreadyExists);
+        return;
+        }
+
+    TInt err = KErrNone;
+    if ( !iTunerControl )
+        {
+        if ( !iTunerControlObserver )
+            {
+            TRAP(err, iTunerControlObserver = CRadioServerFMTuner::NewL(*this));
+            }
+        if ( err == KErrNone )
+            {
+            TRAP(err, iTunerControl = CFMRadioTunerControl::NewL(*iTunerControlObserver));
+            if ( err == KErrNone )
+                {
+                RADIO_RDEBUG(_L("[RADIO-SVR] ProcessRequestTunerControl() - objects created"));
+                iTunerCaps = iTunerControl->Capabilities();
+                // RadioServer does not support dual tuner. Update the tuner capability to
+                // disable dual tuner support even if the adaptation supports it.
+                iTunerCaps.iTunerFunctions = (iTunerCaps.iTunerFunctions & 0x03);
+
+#ifdef RD_FM_RADIO_ENHANCEMENTS
+                iRdsControl = iTunerControl->RdsControl(*iTunerControlObserver);
+                if ( iRdsControl )
+                    {
+                    RADIO_RDEBUG(_L("[RADIO-SVR] ProcessRequestTunerControl() - RDS control obtained"));
+                    iRdsControl->GetCapabilities(iRdsCaps);
+                    // RadioServer does not support RadioText+. Update the tuner capability to
+                    // disable RadioText+ support even if the adaptation supports it.
+                    iRdsCaps.iRdsFunctions = (iRdsCaps.iRdsFunctions & 0x1EF);
+                    }
+#endif
+                }
+            }
+        }
+    // AK - begin: (CPHU-73YTQW)
+    else
+        {
+        RecreateFmTunerControl();
+        }
+    // - end
+
+    if ( err == KErrNone )
+        {
+        if ( !AllowRadioInOfflineMode() )
+            {
+            RADIO_RDEBUG(_L("[RADIO-SVR] ProcessRequestTunerControl(): Offline"));
+            err = KRadioServErrOfflineMode;
+            }
+        else if ( iSettings->IsTransmitterActive() )
+            {
+            RADIO_RDEBUG(_L("[RADIO-SVR] ProcessRequestTunerControl(): Transmitter active"));
+            err = KRadioServErrFmTransmitterActive;
+            }
+        else if ( !iSettings->IsAntennaAttached() )
+            {
+            RADIO_RDEBUG(_L("[RADIO-SVR] ProcessRequestTunerControl(): Antenna not attached"));
+            err = KRadioServErrAntennaNotConnected;
+            }
+        }
+
+    if ( err == KErrNone )
+        {
+        iTunerOnTrigger = ETriggerTunerControl;
+        TFMRadioFrequencyRange freqRange = TunerControlFreqRange( iSettings->FrequencyRange() );
+        iTunerControl->TunerOn(freqRange, iSettings->Frequency());
+        }
+    else
+        {
+        RADIO_RDEBUG_INT(_L("[RADIO-SVR] ProcessRequestTunerControl() - unabled to create tuner. err=[%d]"), err);
+        CompleteAsyncRequest(err);
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessSetFrequencyRange
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::ProcessSetFrequencyRange(
+    TRsFrequencyRange aRange )
+    {
+    RADIO_RDEBUG_INT2(_L("[RADIO-SVR] ProcessSetFrequencyRange(%d) State[%d]"), aRange, iState);
+    if ( aRange == ERsRangeFmEuroAmerica || aRange == ERsRangeFmJapan )
+        {
+        if ( (iSettings->FrequencyRange()) == aRange )
+            {
+            // Same range; no further action needed
+            CompleteAsyncRequest(KErrNone);
+            return;
+            }
+
+        if ( iState == EStatePlaying )
+            {
+            iState = EStateTunerOff;
+            iFreqRange = aRange;
+            iDevSound->Stop();
+            iSettings->SetRadioOff(KErrNone);
+            iTunerControl->TunerOff();
+            // This request is completed upon TunerOffComplete()
+            SetTspTargetClient( ERsPlayerIdle );
+            }
+        else if ( iState == EStateTunerOn )
+            {
+            iState = EStateTunerOff;
+            iFreqRange = aRange;
+            iTunerControl->TunerOff();
+            // This request is completed upon TunerOffComplete()
+            }
+        else
+            {
+            CompleteAsyncRequest(KErrNotReady);
+            }
+        }
+    else
+        {
+        CompleteAsyncRequest(KErrNotSupported);
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessSetFrequency
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::ProcessSetFrequency(
+    TInt aFrequency )
+    {
+    RADIO_RDEBUG_INT2(_L("[RADIO-SVR] ProcessSetFrequency(%d) State[%d]"), aFrequency, iState);
+    switch ( iState )
+        {
+        case EStateTunerOn:
+        case EStatePlaying:
+            if( iSettings->Frequency() == aFrequency )
+                {
+                // Same frequency
+                CompleteAsyncRequest(KErrNone);
+                }
+            else
+                {
+                iTunerControl->SetFrequency(aFrequency);
+                }
+            break;
+        case EStateTunerOff:
+            if ( iSettings->IsAntennaAttached() && AllowRadioInOfflineMode()
+                    && !iSettings->IsTransmitterActive() )
+                {
+                RADIO_RDEBUG(_L("[RADIO-SVR] ProcessSetFrequency() - Sent TunerOn request"));
+                RecreateFmTunerControl();
+                iTunerOnTrigger = ETriggerSetFrequency;
+                TFMRadioFrequencyRange freqRange = TunerControlFreqRange( iSettings->FrequencyRange() );
+                iTunerControl->TunerOn(freqRange, aFrequency);
+                }
+            else
+                {
+                RADIO_RDEBUG(_L("[RADIO-SVR] ProcessSetFrequency - KErrNotReady"));
+                CompleteAsyncRequest(KErrNotReady);
+                }
+            break;
+        case EStateStarted:
+            CompleteAsyncRequest(KErrNotReady);
+            break;
+        default :
+            break;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessStationSeek
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::ProcessStationSeek(
+    TBool aUpwards )
+    {
+    RADIO_RDEBUG_INT2(_L("[RADIO-SVR] ProcessStationSeek(%d) State[%d]"), aUpwards, iState);
+    switch ( iState )
+        {
+        case EStateTunerOn:
+        case EStatePlaying:
+            if ( iState == EStatePlaying )
+                {
+                if ( iSettings->IsSquelchEnabled() && !iSettings->IsMute() )
+                    {
+                    // Simulate squelching
+                    iDevSound->SetVolume(0);
+                    iSquelch = ETrue;
+                    }
+                }
+            if ( aUpwards )
+                {
+                iTunerControl->StationSeek(EFMRadioSeekUp);
+                }
+            else
+                {
+                iTunerControl->StationSeek(EFMRadioSeekDown);
+                }
+            break;
+        case EStateStarted:
+        case EStateTunerOff:
+            CompleteAsyncRequest(KErrNotReady);
+            break;
+        default :
+            break;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessPlay
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::ProcessPlay()
+    {
+    RADIO_RDEBUG_INT(_L("[RADIO-SVR] ProcessPlay() State[%d]"), iState);
+    switch ( iState )
+        {
+        case EStateTunerOn:
+            TRAPD(err, DoPlayL());
+            if ( err == KErrNone )
+                {
+                iState = EStatePlaying;
+                iPreEmpted = EFalse;
+                iSettings->SetRadioOn();
+                // Notify secondary clients that radio is now playing. This should trigger
+                // secondary clients to create a session to observe for events.
+                iSettings->SetRadioMonitorStatus(ETrue);
+                SetTspTargetClient( ERsPlayerPlaying );
+                }
+            RADIO_RDEBUG_INT(_L("[RADIO-SVR] ProcessPlay() DevSound err=[%d]"), err);
+            CompleteAsyncRequest(err);
+            break;
+        case EStatePlaying:
+            // Already playing
+            CompleteAsyncRequest(KErrNone);
+            break;
+        case EStateTunerOff:
+            if ( iSettings->IsAntennaAttached() && AllowRadioInOfflineMode()
+                    && !iSettings->IsTransmitterActive() )
+                {
+                RADIO_RDEBUG(_L("[RADIO-SVR] ProcessPlay() - Sent TunerOn request"));
+                RecreateFmTunerControl();
+                iTunerOnTrigger = ETriggerPlay;
+                TFMRadioFrequencyRange freqRange = TunerControlFreqRange( iSettings->FrequencyRange() );
+                iTunerControl->TunerOn(freqRange, iSettings->Frequency());
+                }
+            else
+                {
+                RADIO_RDEBUG(_L("[RADIO-SVR] ProcessPlay - KErrNotReady"));
+                CompleteAsyncRequest(KErrNotReady);
+                }
+            break;
+        default:
+            CompleteAsyncRequest(KErrNotReady);
+            break;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessStop
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::ProcessStop(
+    TBool aIfOnlyPrimaryClient )
+    {
+    RADIO_RDEBUG_INT2(_L("[RADIO-SVR] ProcessStop(%d) State[%d]"), aIfOnlyPrimaryClient, iState);
+    if ( iState == EStatePlaying )
+        {
+        if ( aIfOnlyPrimaryClient && (iSessionCountPrimary > 1) )
+            {
+            // Client has requested stop only if the requesting client is the only primary client.
+            // There are other clients, so don't stop the audio in this case.
+            return;
+            }
+        iState = EStateTunerOn;
+        // Stop ongoing playback. This is synchronous function.
+        iDevSound->Stop();
+        iSettings->SetRadioOff(KErrNone);
+        SetTspTargetClient( ERsPlayerIdle );
+        }
+    CompleteAsyncRequest(KErrNone);
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessStationSeekByPTY
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::ProcessStationSeekByPTY(
+    TRsRdsProgrammeType aPty,
+    TBool aSeekUp )
+    {
+    RADIO_RDEBUG_INT3(_L("[RADIO-SVR] ProcessStationSeekByPTY(%d, %d) State[%d]"), aPty, aSeekUp, iState);
+    switch ( iState )
+        {
+        case EStateTunerOn:
+        case EStatePlaying:
+            if ( !iRdsControl )
+                {
+                CompleteAsyncRequest(KErrNotSupported);
+                return;
+                }
+
+            if ( iSettings->IsSquelchEnabled() && !iSettings->IsMute() )
+                {
+                // Simulate squelching
+                iDevSound->SetVolume(0);
+                iSquelch = ETrue;
+                }
+            iRdsControl->StationSeekByPTY(aPty, aSeekUp);
+            break;
+        case EStateStarted:
+        case EStateTunerOff:
+            CompleteAsyncRequest(KErrNotReady);
+            break;
+        default :
+            break;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessStationSeekByTA
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::ProcessStationSeekByTA(
+    TBool aSeekUp )
+    {
+    RADIO_RDEBUG_INT2(_L("[RADIO-SVR] ProcessStationSeekByTA(%d) State[%d]"), aSeekUp, iState);
+    switch ( iState )
+        {
+        case EStateTunerOn:
+        case EStatePlaying:
+            if ( !iRdsControl )
+                {
+                CompleteAsyncRequest(KErrNotSupported);
+                return;
+                }
+
+            if ( iSettings->IsSquelchEnabled() && !iSettings->IsMute() )
+                {
+                // Simulate squelching
+                iDevSound->SetVolume(0);
+                iSquelch = ETrue;
+                }
+            iRdsControl->StationSeekByTA(aSeekUp);
+            break;
+        case EStateStarted:
+        case EStateTunerOff:
+            CompleteAsyncRequest(KErrNotReady);
+            break;
+        default :
+            break;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessStationSeekByTP
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::ProcessStationSeekByTP(
+    TBool aSeekUp )
+    {
+    RADIO_RDEBUG_INT2(_L("[RADIO-SVR] ProcessStationSeekByTP(%d) State[%d]"), aSeekUp, iState);
+    switch ( iState )
+        {
+        case EStateTunerOn:
+        case EStatePlaying:
+            if ( !iRdsControl )
+                {
+                CompleteAsyncRequest(KErrNotSupported);
+                return;
+                }
+
+            if ( iSettings->IsSquelchEnabled() && !iSettings->IsMute() )
+                {
+                // Simulate squelching
+                iDevSound->SetVolume(0);
+                iSquelch = ETrue;
+                }
+            iRdsControl->StationSeekByTP(aSeekUp);
+            break;
+        case EStateStarted:
+        case EStateTunerOff:
+            CompleteAsyncRequest(KErrNotReady);
+            break;
+        default :
+            break;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessRemovePrimaryClient
+// -----------------------------------------------------------------------------
+//
+TInt CRadioServer::ProcessRemovePrimaryClientL(
+    const RMessage2& aMessage )
+    {
+#ifdef RD_TSP_CLIENT_MAPPER
+
+    RThread client;
+    aMessage.ClientL( client, EOwnerProcess );
+    RProcess process;
+    client.Process( process );
+    TInt index = iClientPids.Find( process.Id() );
+    if ( index != KErrNotFound )
+        {
+        iClientPids.Remove( index );
+        if ( iProcessId == process.Id() )
+            {
+            iMapper->RemoveTspTargetClient( iTspState, iProcessId );
+            if ( iClientPids.Count() && iState == EStatePlaying ) // still primary clients remaining
+                {
+                iProcessId = iClientPids[0];
+                RADIO_RDEBUG_INT( _L("RADIO-SVR] ProcessRemovePrimaryClient() pid[%d]"), (TInt)iProcessId );
+                iMapper->SetTspTargetClient( CTspClientMapper::EPlayingClients, iProcessId );
+                iTspState = CTspClientMapper::EPlayingClients;
+                }
+            }
+        }
+
+#endif // RD_TSP_CLIENT_MAPPER
+
+    if ( --iSessionCountPrimary == 0 )
+        {
+        RADIO_RDEBUG(_L("[RADIO-SVR] ProcessRemovePrimaryClient() - last primary"));
+        iSettings->SetRadioMonitorStatus(EFalse);
+        }
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessGetTunerCapabilities
+// -----------------------------------------------------------------------------
+//
+TInt CRadioServer::ProcessGetTunerCapabilities(
+    const RMessage2& aMessage )
+    {
+    RADIO_RDEBUG_INT(_L("[RADIO-SVR] ProcessGetTunerCapabilities() State[%d]"), iState);
+    if ( iState == EStateStarted )
+        {
+        return KErrNotReady;
+        }
+
+    TRsTunerCapabilities caps;
+    caps.iFrequencyRange = iTunerCaps.iTunerBands;
+    caps.iCapabilities = iTunerCaps.iTunerFunctions;
+
+    TPckgBuf<TRsTunerCapabilities> p(caps);
+    aMessage.Write(1, p);
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessEnableTunerInOfflineMode
+// -----------------------------------------------------------------------------
+//
+TInt CRadioServer::ProcessEnableTunerInOfflineMode(
+    TBool aEnable )
+    {
+    RADIO_RDEBUG_INT(_L("[RADIO-SVR] ProcessEnableTunerInOfflineMode(%d)"), aEnable);
+    TInt err = KErrNone;
+    if ( iState == EStateStarted )
+        {
+        iEnableTunerInOffline = aEnable;
+        }
+    else
+        {
+        if ( iTunerCaps.iTunerFunctions & 0x01 ) // ETunerAvailableInOfflineMode
+            {
+            // Tuner supports playing radio in offline mode
+            iEnableTunerInOffline = aEnable;
+            }
+        else
+            {
+            err = KErrNotSupported;
+            }
+        }
+    return err;
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessGetFrequencyRange
+// -----------------------------------------------------------------------------
+//
+TInt CRadioServer::ProcessGetFrequencyRange(
+    const RMessage2& aMessage )
+    {
+    RADIO_RDEBUG_INT(_L("[RADIO-SVR] ProcessGetFrequencyRange() State[%d]"), iState);
+    if ( iState == EStateStarted )
+        {
+        return KErrNotReady;
+        }
+
+    TRsFrequencyRange range;
+    TInt minFreq;
+    TInt maxFreq;
+    TInt err = iSettings->GetFrequencyRange(range, minFreq, maxFreq);
+    RADIO_RDEBUG_INT(_L("[RADIO-SVR] ProcessGetFrequencyRange() - [%d]"), err);
+    RADIO_RDEBUG_INT3(_L("[RADIO-SVR] ProcessGetFrequencyRange() - [%d, %d, %d]"), range, minFreq, maxFreq);
+    if ( err == KErrNone )
+        {
+        TPckgBuf<TRsFrequencyRange> pkg1(range);
+        aMessage.Write(1, pkg1);
+        TPckgBuf<TInt> pkg2(minFreq);
+        aMessage.Write(2, pkg2);
+        TPckgBuf<TInt> pkg3(maxFreq);
+        aMessage.Write(3, pkg3);
+        }
+    return err;
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessGetFrequency
+// -----------------------------------------------------------------------------
+//
+TInt CRadioServer::ProcessGetFrequency(
+    const RMessage2& aMessage )
+    {
+    RADIO_RDEBUG_INT(_L("[RADIO-SVR] ProcessGetFrequency() State[%d]"), iState);
+    if ( iState == EStateStarted )
+        {
+        return KErrNotReady;
+        }
+
+    TPckgBuf<TInt> p(iSettings->Frequency());
+    aMessage.Write(1, p);
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessGetForceMonoReception
+// -----------------------------------------------------------------------------
+//
+TInt CRadioServer::ProcessGetForceMonoReception(
+    const RMessage2& aMessage )
+    {
+    RADIO_RDEBUG_INT(_L("[RADIO-SVR] ProcessGetForceMonoReception() State[%d]"), iState);
+    if ( iState == EStateStarted )
+        {
+        return KErrNotReady;
+        }
+
+    TPckgBuf<TBool> p(iSettings->IsForceMonoEnabled());
+    aMessage.Write(1,p);
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessSetSquelch
+// -----------------------------------------------------------------------------
+//
+TInt CRadioServer::ProcessSetSquelch(
+    TBool aEnabled )
+    {
+    RADIO_RDEBUG_INT2(_L("[RADIO-SVR] ProcessSetSquelch(%d) State[%d]"), aEnabled, iState);
+    if ( iState == EStateStarted )
+        {
+        return KErrNotReady;
+        }
+
+    // Squelch is handled internally in RadioServer instead of requesting it to the tuner control
+    iSettings->SetSquelch(aEnabled);
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessGetSquelch
+// -----------------------------------------------------------------------------
+//
+TInt CRadioServer::ProcessGetSquelch(
+    const RMessage2& aMessage )
+    {
+    RADIO_RDEBUG_INT(_L("[RADIO-SVR] ProcessGetSquelch() State[%d]"), iState);
+    if ( iState == EStateStarted )
+        {
+        return KErrNotReady;
+        }
+
+    TPckgBuf<TBool> p(iSettings->IsSquelchEnabled());
+    aMessage.Write(1,p);
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessSyncRequest
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::ProcessSyncRequest(
+    TRadioMessageRequestData* aRequest )
+    {
+    // Set the current outstanding request
+    iSyncRequest = aRequest;
+    switch( aRequest->iType )
+        {
+        case ERadioServGetSignalStrength:
+            ProcessGetSignalStrength();
+            break;
+        case ERadioServGetMaxSignalStrength:
+            ProcessGetMaxSignalStrength();
+            break;
+        case ERadioServGetStereoMode:
+            ProcessGetStereoMode();
+            break;
+        case ERadioServForceMonoReception:
+            ProcessForceMonoReception(aRequest->iMessage.Int1());
+            break;
+        default:
+            break;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessGetSignalStrength
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::ProcessGetSignalStrength()
+    {
+    RADIO_RDEBUG_INT(_L("[RADIO-SVR] ProcessGetSignalStrength() State[%d]"), iState);
+    if ( iState == EStateTunerOn || iState == EStatePlaying )
+        {
+        // The request is completed once SignalStrengthComplete() is received from tuner control
+        iTunerControl->SignalStrength();
+        }
+    else
+        {
+        CompleteSyncRequest(KErrNotReady);
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessGetMaxSignalStrength
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::ProcessGetMaxSignalStrength()
+    {
+    RADIO_RDEBUG_INT(_L("[RADIO-SVR] ProcessGetMaxSignalStrength() State[%d]"), iState);
+    switch ( iState )
+        {
+        case EStateStarted:
+            CompleteSyncRequest(KErrNotReady);
+            break;
+        case EStateTunerOn:
+        case EStatePlaying:
+            if ( iMaxSigStrength > 0 )
+                {
+                // This value is constant once we get it from the tuner. If the value is
+                // already available, there is no need to get it again from the tuner.
+                TPckgBuf<TInt> p(iMaxSigStrength);
+                iSyncRequest->iMessage.Write(1, p);
+                CompleteSyncRequest(KErrNone);
+                }
+            else
+                {
+                // The request is completed once MaxSignalStrengthComplete() is received from tuner control
+                iTunerControl->MaxSignalStrength();
+                }
+            break;
+        case EStateTunerOff:
+            if ( iMaxSigStrength > 0 )
+                {
+                // This value is constant once we get it from the tuner. If the value is
+                // already available, there is no need to get it again from the tuner.
+                TPckgBuf<TInt> p(iMaxSigStrength);
+                iSyncRequest->iMessage.Write(1, p);
+                CompleteSyncRequest(KErrNone);
+                }
+            else
+                {
+                CompleteSyncRequest(KErrNotReady);
+                }
+            break;
+        default:
+            break;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessGetStereoMode
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::ProcessGetStereoMode()
+    {
+    RADIO_RDEBUG_INT(_L("[RADIO-SVR] ProcessGetStereoMode() State[%d]"), iState);
+    if ( iState == EStateTunerOn || iState == EStatePlaying )
+        {
+        // The request is completed once AudioModeComplete() is received from tuner control
+        iTunerControl->AudioMode();
+        }
+    else
+        {
+        CompleteSyncRequest(KErrNotReady);
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessForceMonoReception
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::ProcessForceMonoReception(
+    TBool aForcedMono )
+    {
+    RADIO_RDEBUG_INT2(_L("[RADIO-SVR] ProcessForceMonoReception(%d) State[%d]"), aForcedMono, iState);
+    if ( aForcedMono == iSettings->IsForceMonoEnabled() )
+        {
+        RADIO_RDEBUG(_L("[RADIO-SVR] ProcessForceMonoReception() - no change"));
+        CompleteSyncRequest(KErrNone);
+        return;
+        }
+
+    if ( iState == EStateTunerOn || iState == EStatePlaying )
+        {
+        TFMRadioAudioMode mode;
+        if ( aForcedMono )
+            {
+            if ( (iChannels == EChannelBoth) || (iChannels == EChannelMono) )
+                {
+                mode = EFMRadioAudioMono;
+                }
+            else
+                {
+                RADIO_RDEBUG(_L("[RADIO-SVR] ProcessForceMonoReception() - unable to set to Mono"));
+                CompleteSyncRequest(KErrNotSupported);
+                return;
+                }
+            }
+        else
+            {
+            if ( (iChannels == EChannelBoth) || (iChannels == EChannelStereo) )
+                {
+                mode = EFMRadioAudioStereo;
+                }
+            else
+                {
+                RADIO_RDEBUG(_L("[RADIO-SVR] DoPlayL() - unable to set to stereo"));
+                CompleteSyncRequest(KErrNotSupported);
+                return;
+                }
+            }
+        // The request is completed once SetAudioModeComplete() is received from tuner control.
+        iTunerControl->SetAudioMode(mode);
+        }
+    else
+        {
+        CompleteSyncRequest(KErrNotReady);
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessGetPlayerState
+// -----------------------------------------------------------------------------
+//
+TInt CRadioServer::ProcessGetPlayerState(
+    const RMessage2& aMessage )
+    {
+    RADIO_RDEBUG_INT(_L("[RADIO-SVR] ProcessGetPlayerState() State[%d]"), iState);
+    TRsPlayerState state = ERsPlayerIdle;
+    if ( iState == EStatePlaying )
+        {
+        state = ERsPlayerPlaying;
+        }
+    TPckgBuf<TRsPlayerState> p(state);
+    aMessage.Write(1,p);
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessGetMaxVolume
+// -----------------------------------------------------------------------------
+//
+TInt CRadioServer::ProcessGetMaxVolume(
+    const RMessage2& aMessage )
+    {
+    RADIO_RDEBUG(_L("[RADIO-SVR] ProcessGetMaxVolume()"));
+    TPckgBuf<TInt> p(iMaxVolume);
+    aMessage.Write(1, p);
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessSetVolume
+// -----------------------------------------------------------------------------
+//
+TInt CRadioServer::ProcessSetVolume(
+    TInt aVolume )
+    {
+    RADIO_RDEBUG_INT(_L("[RADIO-SVR] ProcessSetVolume(%d)"), aVolume);
+    if ( aVolume < 0 || aVolume > iMaxVolume )
+        {
+        return KErrArgument;
+        }
+
+    if ( aVolume != iSettings->Volume() )
+        {
+        if ( !iSettings->IsMute() )
+            {
+            iDevSound->SetVolume(aVolume);
+            }
+        iSettings->SetVolume(aVolume);
+        }
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessGetVolume
+// -----------------------------------------------------------------------------
+//
+TInt CRadioServer::ProcessGetVolume(
+    const RMessage2& aMessage )
+    {
+    RADIO_RDEBUG(_L("[RADIO-SVR] ProcessGetMaxVolume()"));
+    TPckgBuf<TInt> p(iSettings->Volume());
+    aMessage.Write(1, p);
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessSetVolumeRamp
+// -----------------------------------------------------------------------------
+//
+TInt CRadioServer::ProcessSetVolumeRamp(
+    const RMessage2& aMessage )
+    {
+    TTimeIntervalMicroSeconds rampDuration(0);
+    TPckg<TTimeIntervalMicroSeconds> rampDurationPckg(rampDuration);
+    TInt err = aMessage.Read(1, rampDurationPckg);
+    RADIO_RDEBUG_INT2(_L("[RADIO-SVR] ProcessSetVolumeRamp(%d) err[%d]"), I64INT(rampDuration.Int64()), err);
+    if ( err == KErrNone )
+        {
+        iDevSound->SetVolumeRamp(rampDuration);
+        }
+    return err;
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessSetMute
+// -----------------------------------------------------------------------------
+//
+TInt CRadioServer::ProcessSetMute(
+    TBool aMute )
+    {
+    RADIO_RDEBUG_INT(_L("[RADIO-SVR] ProcessSetMute(%d)"), aMute);
+    if ( aMute && !iSettings->IsMute() )
+        {
+        iDevSound->SetVolume(0);
+        }
+    else if ( !aMute && iSettings->IsMute() )
+        {
+        // Restore the last volume
+        iDevSound->SetVolume(iSettings->Volume());
+        }
+    iSettings->SetMuteStatus(aMute);
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessGetMuteStatus
+// -----------------------------------------------------------------------------
+//
+TInt CRadioServer::ProcessGetMuteStatus(
+    const RMessage2& aMessage )
+    {
+    RADIO_RDEBUG(_L("[RADIO-SVR] ProcessGetMuteStatus()"));
+    TPckgBuf<TBool> p(iSettings->IsMute());
+    aMessage.Write(1,p);
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessSetBalance
+// -----------------------------------------------------------------------------
+//
+TInt CRadioServer::ProcessSetBalance(
+    TInt aLeft,
+    TInt aRight )
+    {
+    RADIO_RDEBUG_INT2(_L("[RADIO-SVR] ProcessSetBalance(%d, %d)"), aLeft, aRight);
+    if ( (aLeft < KRadioServerBalanceMin) || (aLeft > KRadioServerBalanceMax)
+         || (aRight < KRadioServerBalanceMin) || (aRight > KRadioServerBalanceMax) )
+        {
+        return KErrArgument;
+        }
+
+    TInt err = KErrNone;
+    TInt left, right;
+    iSettings->GetBalance(left, right);
+    if ( (left != aLeft) || (right != aRight) )
+        {
+        TRAP(err, iDevSound->SetPlayBalanceL(aLeft, aRight));
+        if( err == KErrNone )
+            {
+            iSettings->SetBalance(aLeft, aRight);
+            }
+        }
+    return err;
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessGetBalance
+// -----------------------------------------------------------------------------
+//
+TInt CRadioServer::ProcessGetBalance(
+    const RMessage2& aMessage )
+    {
+    TInt left, right;
+    iSettings->GetBalance(left, right);
+    TPckgBuf<TInt> p1(left);
+    TPckgBuf<TInt> p2(right);
+    aMessage.Write(1,p1);
+    aMessage.Write(2,p2);
+    return KErrNone;
+    }
+
+/***********************************************************
+ *   MRdsControl & MRdsControlObserver Begins
+ ***********************************************************/
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessGetRdsCapabilities
+// -----------------------------------------------------------------------------
+//
+TInt CRadioServer::ProcessGetRdsCapabilities(
+    const RMessage2& aMessage )
+    {
+    RADIO_RDEBUG_INT(_L("[RADIO-SVR] ProcessGetRdsCapabilities() State[%d]"), iState);
+    if ( iState == EStateStarted )
+        {
+        return KErrNotReady;
+        }
+
+    TInt err = KErrNone;
+    if ( iRdsControl )
+        {
+        TRsRdsCapabilities caps;
+        caps.iRdsFunctions = iRdsCaps.iRdsFunctions;
+        TPckgBuf<TRsRdsCapabilities> p(caps);
+        aMessage.Write(1, p);
+        }
+    else
+        {
+        err = KErrNotSupported;
+        }
+    return err;
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessGetRdsSignalStatus
+// -----------------------------------------------------------------------------
+//
+TInt CRadioServer::ProcessGetRdsSignalStatus(
+    const RMessage2& aMessage )
+    {
+    RADIO_RDEBUG_INT(_L("[RADIO-SVR] ProcessGetRdsSignalStatus() State[%d]"), iState);
+    if ( iState == EStateStarted )
+        {
+        return KErrNotReady;
+        }
+
+    TInt err = KErrNone;
+    if ( iRdsControl )
+        {
+        TBool signalStatus;
+        err = iRdsControl->GetRdsSignalStatus(signalStatus);
+        if ( err == KErrNone )
+            {
+            TPckgBuf<TBool> pkg(signalStatus);
+            aMessage.Write(1, pkg);
+            }
+        }
+    else
+        {
+        err = KErrNotSupported;
+        }
+    return err;
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessNotifyRdsDataChange
+// -----------------------------------------------------------------------------
+//
+TInt CRadioServer::ProcessNotifyRdsDataChange(
+        const RMessage2& aMessage )
+        {
+        RADIO_RDEBUG_INT(_L("[RADIO-SVR] ProcessNotifyRdsDataChange() State[%d]"), iState);
+        if ( iState == EStateStarted )
+            {
+            return KErrNotReady;
+            }
+
+        TInt err = KErrNone;
+        if ( iRdsControl )
+            {
+            if ( iRdsNotifyClientIdArray.Count() == 0 )
+                {
+                TRdsData data;
+                data.iRdsFunctions = TRdsData::KAllRdsData;
+                data.iAdditionalFunctions1 = 0;     // To suppress compiler warning
+                data.iAdditionalFunctions2 = 0;     // To suppress compiler warning
+                err = iRdsControl->NotifyRdsDataChange(data);
+                }
+            if ( err == KErrNone )
+                {
+                RThread clientThread;
+                TInt error = aMessage.Client(clientThread);
+                if ( error == KErrNone )
+                    {
+                    TUint clientId = clientThread.Id().operator TUint();
+                    AddRdsNotifyClientId(clientId);
+                    }
+                }
+            }
+        else
+            {
+            err = KErrNotSupported;
+            }
+        return err;
+        }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessCancelNotifyRdsDataChange
+// -----------------------------------------------------------------------------
+//
+TInt CRadioServer::ProcessCancelNotifyRdsDataChange(
+        const RMessage2& aMessage )
+        {
+        RADIO_RDEBUG(_L("[RADIO-SVR] ProcessCancelNotifyRdsDataChange()"));
+        if ( iRdsNotifyClientIdArray.Count() > 0 )
+            {
+            RThread clientThread;
+            TInt error = aMessage.Client(clientThread);
+            if ( error == KErrNone )
+                {
+                TUint clientId = clientThread.Id().operator TUint();
+                RADIO_RDEBUG_INT(_L("[RADIO-SVR] ProcessCancelNotifyRdsDataChange() clientID[%d]"), clientId);
+                RemoveRdsNotifyClientId(clientId);
+                }
+            if ( iRdsNotifyClientIdArray.Count() == 0 )
+                {
+                if ( iRdsControl )
+                    {
+                    iRdsControl->CancelNotifyRdsDataChange();
+                    }
+                }
+            }
+        return KErrNone;
+        }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessSetAutomaticSwitching
+// -----------------------------------------------------------------------------
+//
+TInt CRadioServer::ProcessSetAutomaticSwitching(
+    TBool aAuto )
+    {
+    RADIO_RDEBUG_INT2(_L("[RADIO-SVR] ProcessSetAutomaticSwitching(%d) State[%d]"), aAuto, iState);
+    if ( iState == EStateStarted )
+        {
+        return KErrNotReady;
+        }
+
+    TInt err = KErrNone;
+    if ( iRdsControl )
+        {
+        err = iRdsControl->SetAutomaticSwitching(aAuto);
+        if ( err == KErrNone )
+            {
+            iSettings->SetAutoSwitchStatus(aAuto);
+            }
+        }
+    else
+        {
+        err = KErrNotSupported;
+        }
+    return err;
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessGetAutomaticSwitching
+// -----------------------------------------------------------------------------
+//
+TInt CRadioServer::ProcessGetAutomaticSwitching(
+    const RMessage2& aMessage )
+    {
+    RADIO_RDEBUG_INT(_L("[RADIO-SVR] ProcessGetAutomaticSwitching() State[%d]"), iState);
+    if ( iState == EStateStarted )
+        {
+        return KErrNotReady;
+        }
+
+    TInt err = KErrNone;
+    if ( iRdsControl )
+        {
+        TPckgBuf<TBool> p(iSettings->AutoSwitch());
+        aMessage.Write(1, p);
+        }
+    else
+        {
+        err = KErrNotSupported;
+        }
+    return err;
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessCancelAFSearch
+// -----------------------------------------------------------------------------
+//
+TInt CRadioServer::ProcessCancelAFSearch()
+    {
+    RADIO_RDEBUG_INT(_L("[RADIO-SVR] ProcessCancelAFSearch() State[%d]"), iState);
+    if ( iRdsControl )
+        {
+        iRdsControl->CancelAFSearch();
+        }
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessGetProgrammeIdentification
+// -----------------------------------------------------------------------------
+//
+TInt CRadioServer::ProcessGetProgrammeIdentification(
+    const RMessage2& aMessage )
+    {
+    RADIO_RDEBUG_INT(_L("[RADIO-SVR] ProcessGetProgrammeIdentification() State[%d]"), iState);
+    if ( iState == EStateStarted )
+        {
+        return KErrNotReady;
+        }
+
+    TInt err = KErrNone;
+    if ( iRdsControl )
+        {
+        TInt pi;
+        err = iRdsControl->GetProgrammeIdentification(pi);
+        if ( err == KErrNone )
+            {
+            TPckgBuf<TInt> p(pi);
+            aMessage.Write(1, p);
+            }
+        }
+    else
+        {
+        err = KErrNotSupported;
+        }
+    return err;
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessGetProgrammeType
+// -----------------------------------------------------------------------------
+//
+TInt CRadioServer::ProcessGetProgrammeType(
+    const RMessage2& aMessage )
+    {
+    RADIO_RDEBUG_INT(_L("[RADIO-SVR] ProcessGetProgrammeType() State[%d]"), iState);
+    if ( iState == EStateStarted )
+        {
+        return KErrNotReady;
+        }
+
+    TInt err = KErrNone;
+    if ( iRdsControl )
+        {
+        TRdsProgrammeType rdsPty;
+        err = iRdsControl->GetProgrammeType(rdsPty);
+        if ( err == KErrNone )
+            {
+            TRsRdsProgrammeType pty = rdsPty;
+            TPckgBuf<TRsRdsProgrammeType> p(pty);
+            aMessage.Write(1, p);
+            }
+        }
+    else
+        {
+        err = KErrNotSupported;
+        }
+    return err;
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessGetProgrammeService
+// -----------------------------------------------------------------------------
+//
+TInt CRadioServer::ProcessGetProgrammeService(
+    const RMessage2& aMessage )
+    {
+    RADIO_RDEBUG_INT(_L("[RADIO-SVR] ProcessGetProgrammeService() State[%d]"), iState);
+    if ( iState == EStateStarted )
+        {
+        return KErrNotReady;
+        }
+
+    TInt err = KErrNone;
+    if ( iRdsControl )
+        {
+        TRdsPSName rdsPs;
+        err = iRdsControl->GetProgrammeService(rdsPs);
+        if ( err == KErrNone )
+            {
+            TRsRdsPSName ps;
+            ps.Copy(rdsPs);
+            TPckgBuf<TRsRdsPSName> p(ps);
+            aMessage.Write(1, p);
+            }
+        }
+    else
+        {
+        err = KErrNotSupported;
+        }
+    return err;
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessGetRadioText
+// -----------------------------------------------------------------------------
+//
+TInt CRadioServer::ProcessGetRadioText(
+    const RMessage2& aMessage )
+    {
+    RADIO_RDEBUG_INT(_L("[RADIO-SVR] ProcessGetRadioText() State[%d]"), iState);
+    if ( iState == EStateStarted )
+        {
+        return KErrNotReady;
+        }
+
+    TInt err = KErrNone;
+    if ( iRdsControl )
+        {
+        TRdsRadioText rdsRt;
+        RArray<TRdsRTplusTag> rtTags;
+        err = iRdsControl->GetRadioText(rdsRt, rtTags);
+        rtTags.Close();
+        if ( err == KErrNone )
+            {
+            TRsRdsRadioText rt;
+            rt.Copy(rdsRt);
+            TPckgBuf<TRsRdsRadioText> p(rt);
+            aMessage.Write(1, p);
+            }
+        }
+    else
+        {
+        err = KErrNotSupported;
+        }
+    return err;
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessGetClockTime
+// -----------------------------------------------------------------------------
+//
+TInt CRadioServer::ProcessGetClockTime(
+    const RMessage2& aMessage )
+    {
+    RADIO_RDEBUG_INT(_L("[RADIO-SVR] ProcessGetClockTime() State[%d]"), iState);
+    if ( iState == EStateStarted )
+        {
+        return KErrNotReady;
+        }
+
+    TInt err = KErrNone;
+    if ( iRdsControl )
+        {
+        TDateTime ct;
+        err = iRdsControl->GetClockTime(ct);
+        if ( err == KErrNone )
+            {
+            TPckgBuf<TDateTime> p(ct);
+            aMessage.Write(1, p);
+            }
+        }
+    else
+        {
+        err = KErrNotSupported;
+        }
+    return err;
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessGetTrafficAnnouncementStatus
+// -----------------------------------------------------------------------------
+//
+TInt CRadioServer::ProcessGetTrafficAnnouncementStatus(
+    const RMessage2& aMessage )
+    {
+    RADIO_RDEBUG_INT(_L("[RADIO-SVR] ProcessGetTrafficAnnouncementStatus() State[%d]"), iState);
+    if ( iState == EStateStarted )
+        {
+        return KErrNotReady;
+        }
+
+    TInt err = KErrNone;
+    if ( iRdsControl )
+        {
+        TBool ta;
+        err = iRdsControl->GetTrafficAnnouncementStatus(ta);
+        if ( err == KErrNone )
+            {
+            TPckgBuf<TBool> p(ta);
+            aMessage.Write(1, p);
+            }
+        }
+    else
+        {
+        err = KErrNotSupported;
+        }
+    return err;
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::ProcessGetTrafficProgrammeStatus
+// -----------------------------------------------------------------------------
+//
+TInt CRadioServer::ProcessGetTrafficProgrammeStatus(
+    const RMessage2& aMessage )
+    {
+    RADIO_RDEBUG_INT(_L("[RADIO-SVR] ProcessGetTrafficProgrammeStatus() State[%d]"), iState);
+    if ( iState == EStateStarted )
+        {
+        return KErrNotReady;
+        }
+
+    TInt err = KErrNone;
+    if ( iRdsControl )
+        {
+        TBool tp;
+        err = iRdsControl->GetTrafficProgrammeStatus(tp);
+        if ( err == KErrNone )
+            {
+            TPckgBuf<TBool> p(tp);
+            aMessage.Write(1, p);
+            }
+        }
+    else
+        {
+        err = KErrNotSupported;
+        }
+    return err;
+    }
+
+// ----------------------------------------------------
+// CRadioServer::CompleteAsyncRequest
+// Complete current outstanding request
+// ----------------------------------------------------
+//
+void CRadioServer::CompleteAsyncRequest(
+    TInt aErrorCode )
+    {
+    if ( iAsyncRequest && !(iAsyncRequest->iMessage.IsNull()) )
+        {
+        RADIO_RDEBUG_INT2(_L("[RADIO-SVR] CompleteAsyncRequest(%d, %d) - Client alive"), iAsyncRequest->iType, aErrorCode);
+        iAsyncRequest->iMessage.Complete(aErrorCode);
+        }
+    else
+        {
+        RADIO_RDEBUG_INT2(_L("[RADIO-SVR] CompleteAsyncRequest(%d, %d) - Client gone"), iAsyncRequest->iType, aErrorCode);
+        }
+
+    delete iAsyncRequest;
+    iAsyncRequest = NULL;
+    ProcessNextItemInQueue(iAsyncRequestQue);
+    }
+
+// ----------------------------------------------------
+// CRadioServer::CompleteSyncRequest
+// Complete current outstanding request
+// ----------------------------------------------------
+//
+void CRadioServer::CompleteSyncRequest(
+    TInt aErrorCode )
+    {
+    if ( iSyncRequest && !(iSyncRequest->iMessage.IsNull()) )
+        {
+        RADIO_RDEBUG_INT2(_L("[RADIO-SVR] CompleteSyncRequest(%d, %d) - Client alive"), iSyncRequest->iType, aErrorCode);
+        iSyncRequest->iMessage.Complete(aErrorCode);
+        }
+    else
+        {
+        RADIO_RDEBUG_INT2(_L("[RADIO-SVR] CompleteAsyncRequest(%d, %d) - Client gone"), iSyncRequest->iType, aErrorCode);
+        }
+
+    delete iSyncRequest;
+    iSyncRequest = NULL;
+    ProcessNextItemInQueue(iSyncRequestQue);
+    }
+
+// ----------------------------------------------------
+// CRadioServer::RemoveFromQueue
+// ----------------------------------------------------
+//
+void CRadioServer::RemoveFromQueue(
+    TSglQue<TRadioMessageRequestData>& aQue,
+    TRadioServerRequest aMessageType )
+    {
+    TRadioMessageRequestData* request;
+    TSglQueIter<TRadioMessageRequestData> iter(aQue);
+    iter.SetToFirst();
+    request = iter++;
+    while ( request )
+        {
+        if( request->iType == aMessageType )
+            {
+            aQue.Remove(*request);
+            if( !(request->iMessage.IsNull()) )
+                {
+                RADIO_RDEBUG(_L("[RADIO-SVR] RemoveFromQueue()"));
+                request->iMessage.Complete(KErrCancel);
+                }
+            delete request;
+            break;
+            }
+        request = iter++;
+        }
+    }
+
+// ----------------------------------------------------
+// CRadioServer::ProcessNextItemInQueue
+// ----------------------------------------------------
+//
+void CRadioServer::ProcessNextItemInQueue(
+    TSglQue<TRadioMessageRequestData>& aQue )
+    {
+    if ( !aQue.IsEmpty() )
+        {
+        // there is at least one element in the linked list
+        TRadioMessageRequestData* data;
+
+        data = aQue.First();
+        aQue.Remove(*data);
+        ProcessAsyncRequest(data);
+        }
+    }
+
+// ----------------------------------------------------
+// CRadioServer::ClearQueue
+// ----------------------------------------------------
+//
+void CRadioServer::ClearQueue()
+    {
+    while ( !iAsyncRequestQue.IsEmpty() )
+        {
+        iAsyncRequest = iAsyncRequestQue.First();
+        iAsyncRequestQue.Remove(*iAsyncRequest);
+        delete iAsyncRequest;
+        iAsyncRequest = NULL;
+        }
+
+    while ( !iSyncRequestQue.IsEmpty() )
+        {
+        iSyncRequest = iSyncRequestQue.First();
+        iSyncRequestQue.Remove(*iSyncRequest);
+        delete iSyncRequest;
+        iSyncRequest = NULL;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::AllowRadioInOfflineMode
+// -----------------------------------------------------------------------------
+//
+TBool CRadioServer::AllowRadioInOfflineMode()
+    {
+    RADIO_RDEBUG(_L("[RADIO-SVR] AllowRadioInOfflineMode()"));
+    TBool res = EFalse;
+    if ( iSettings->IsOfflineModeEnabled() )
+        {
+        if ( iEnableTunerInOffline && (iTunerCaps.iTunerFunctions & 0x01) ) // ETunerAvailableInOfflineMode
+            {
+            // Only allowed when client requested tuner in offline AND adaptation supports it
+            res = ETrue;
+            }
+        }
+    else
+        {
+        // Phone is not in Offline mode anyways; OK
+        res = ETrue;
+        }
+    return res;
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::GetFrequencyRange
+// -----------------------------------------------------------------------------
+//
+TInt CRadioServer::GetFrequencyRange(
+    TRsFrequencyRange& aRange,
+    TInt& aMinFreq,
+    TInt& aMaxFreq ) const
+    {
+    TInt err = KErrNone;
+#ifdef RD_FM_RADIO_ENHANCEMENTS
+    TFMRadioFrequencyRange range;
+    err = iTunerControl->GetFrequencyRange(range, aMinFreq, aMaxFreq);
+
+    if ( err == KErrNone )
+        {
+        if ( range == EFMRadioFrequencyEuroAmerica )
+            {
+            aRange = ERsRangeFmEuroAmerica;
+            }
+        else
+            {
+            aRange = ERsRangeFmJapan;
+            }
+        }
+#else
+    aRange = iSettings->FrequencyRange();
+    if ( aRange == ERsRangeFmEuroAmerica )
+        {
+        aMinFreq = KEuroAmericaMin;
+        aMaxFreq = KEuroAmericaMax;
+        }
+    else
+        {
+        aMinFreq = KJapanMin;
+        aMaxFreq = KJapanMax;
+        }
+#endif //#ifdef RD_FM_RADIO_ENHANCEMENTS
+    RADIO_RDEBUG_INT(_L("[RADIO-SVR] GetFrequencyRange() err[%d]"), err);
+    return err;
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::TunerControlFreqRange
+// -----------------------------------------------------------------------------
+//
+TFMRadioFrequencyRange CRadioServer::TunerControlFreqRange(
+    TRsFrequencyRange aRange )
+    {
+    if ( aRange == ERsRangeFmEuroAmerica )
+        {
+        return EFMRadioFrequencyEuroAmerica;
+        }
+    else
+        {
+        // Safe to assume; check was already done at ProcessSetFrequencyRange
+        return EFMRadioFrequencyJapan;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::DoPlayL
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::DoPlayL()
+    {
+    RADIO_RDEBUG(_L("[RADIO-SVR] DoPlayL()"));
+    if ( iSettings->IsForceMonoEnabled() )
+        {
+        iDevSoundConfig.iChannels = EMMFMono;
+        }
+    else
+        {
+        iDevSoundConfig.iChannels = EMMFStereo;
+        }
+
+    iDevSound->SetConfigL(iDevSoundConfig);
+    RADIO_RDEBUG(_L("[RADIO-SVR] DoPlayL() - DevSound configured"));
+    iDevSound->PlayInitL();
+    RADIO_RDEBUG(_L("[RADIO-SVR] DoPlayL() - DevSound playInit OK"));
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::RecreateFmTunerControl
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::RecreateFmTunerControl()
+    {
+    RADIO_RDEBUG(_L("[RADIO-SVR] RecreateFmTunerControl()"));
+    // AK - temporary until adaptation fix is available (CPHU-73YTQW)
+    delete iTunerControl;
+    iTunerControl = NULL;
+    iRdsControl = NULL;
+    TRAPD(err, iTunerControl = CFMRadioTunerControl::NewL(*iTunerControlObserver));
+    if ( err != KErrNone )
+        {
+        RADIO_RDEBUG(_L("[RADIO-SVR] RecreateFmTunerControl() - failed to recreate!"));
+        }
+#ifdef RD_FM_RADIO_ENHANCEMENTS
+    if ( iTunerControl )
+        {
+        iRdsControl = iTunerControl->RdsControl(*iTunerControlObserver);
+        if ( !iRdsControl )
+            {
+            RADIO_RDEBUG(_L("[RADIO-SVR] RecreateFmTunerControl() - failed to get RDS Control!"));
+            }
+        }
+#endif
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::AddRdsNotifyClientId
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::AddRdsNotifyClientId( TUint aClientId )
+    {
+    TInt index = iRdsNotifyClientIdArray.Find(aClientId);
+    if ( index == KErrNotFound )
+        {
+        // Client is not in the array, so add client.
+        RADIO_RDEBUG_INT(_L("[RADIO-SVR] AddRdsNotifyClientId() Add client[%d]"), aClientId);
+        iRdsNotifyClientIdArray.Append(aClientId);
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::RemoveRdsNotifyClientId
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::RemoveRdsNotifyClientId( TUint aClientId )
+    {
+    TInt index = iRdsNotifyClientIdArray.Find(aClientId);
+    if ( index != KErrNotFound )
+        {
+        // Client is in the array, so remove client.
+        RADIO_RDEBUG_INT(_L("[RADIO-SVR] RemoveRdsNotifyClientId() Remove client[%d]"), aClientId);
+        iRdsNotifyClientIdArray.Remove(index);
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::SetTspTargetClient
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::SetTspTargetClient(
+    TRsPlayerState aPlayerTargetState )
+    {
+    RADIO_RDEBUG_INT(_L("[RADIO-SVR] SetTspTargetClient(%d)"), aPlayerTargetState);
+#ifdef RD_TSP_CLIENT_MAPPER
+    if ( aPlayerTargetState == ERsPlayerPlaying )
+        {
+        iMapper->SetTspTargetClient( CTspClientMapper::EPlayingClients, iProcessId );
+        iTspState = CTspClientMapper::EPlayingClients;
+        }
+    else if ( aPlayerTargetState == ERsPlayerIdle )
+        {
+        iMapper->SetTspTargetClientToOtherType( CTspClientMapper::EStoppedClients, iProcessId );
+        iTspState = CTspClientMapper::EStoppedClients;
+        }
+#endif // RD_TSP_CLIENT_MAPPER
+    }
+
+// -----------------------------------------------------------------------------
+// CRadioServer::RegisterClientPidL
+// -----------------------------------------------------------------------------
+//
+void CRadioServer::RegisterClientPidL(
+    const RMessage2& aMessage )
+    {
+    RADIO_RDEBUG(_L("[RADIO-SVR] RegisterClientPid()"));
+#ifdef RD_TSP_CLIENT_MAPPER
+
+    RThread client;
+    aMessage.ClientL( client, EOwnerProcess );
+    RProcess process;
+    client.Process( process );
+    iClientPids.Append(process.Id());
+    if ( iClientPids.Count() == 1 )
+        {
+        iProcessId = process.Id();
+        }
+#endif // RD_TSP_CLIENT_MAPPER
+    }
+//  End of File