/*
* Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:   Base class implements volume control of AVRCP Controller.	
*
*
*/

// INCLUDE FILES
#include <remconbeareravrcp.h> //   KRemConBearerAvrcpImplementationUid = 0x1020685f
#include <MediaStreamPropertiesPSKeys.h>
#include <mmkeybearerscancodes.h> // for volume pubsub
#include <mediakeysinternalpskeys.h>
#include <remconinterfaceselector.h> 
#include <remconcoreapicontroller.h> 
#include <remconaddress.h> 
#include <sounddevice.h>

#include "btrccVolumeLevelControllerBase.h"
#include "debug.h"


// MODULE DATA STRUCTURES
const TInt KVolumeChangeListenerServiceId = 0x01; 

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

// -----------------------------------------------------------------------------
// CBTRCCVolumeLevelControllerBase::CBTRCCVolumeLevelController
// C++ constructor.
// -----------------------------------------------------------------------------
//
CBTRCCVolumeLevelControllerBase::CBTRCCVolumeLevelControllerBase(MBTRCCVolumeControllerObserver &aObserver): 
    iObserver(aObserver), iLocalMaxVolume(0), iState(ESubscribePhoneVolume) 
    {
    }

// -----------------------------------------------------------------------------
// CBTRCCVolumeLevelControllerBase::ConstructL
// Symbian 2nd phase constructor.
// -----------------------------------------------------------------------------
//
void CBTRCCVolumeLevelControllerBase::ConstructL()
    {
    TRACE_FUNC
    LEAVE_IF_ERROR(iVolLevelProperty.Attach(KPSUidMediaStreamProperties, KMediaStreamCurrentVolume))
    LEAVE_IF_ERROR(iVolKeyEventProperty.Attach(KPSUidMediaKeysEventNotifier, KMediaKeysAccessoryVolumeEvent))
    iBtrccActive = CBTRCCActive::NewL(*this, KVolumeChangeListenerServiceId); 
    }

// -----------------------------------------------------------------------------
// Destructor.
// -----------------------------------------------------------------------------
//
CBTRCCVolumeLevelControllerBase::~CBTRCCVolumeLevelControllerBase()
    {
    TRACE_FUNC
    delete iBtrccActive; 
    iVolLevelProperty.Close();
    iVolKeyEventProperty.Close();
    }

// -----------------------------------------------------------------------------
// CBTRCCVolumeLevelControllerBase::Start
// -----------------------------------------------------------------------------
//
void CBTRCCVolumeLevelControllerBase::Start() 
    {
    TRACE_FUNC

	iVolLevelProperty.Subscribe(iBtrccActive->iStatus);
    iBtrccActive->GoActive(); 

    (void) GetPhoneVolume(iPhoneVolume);
    ScalePhoneVolume(iPhoneVolume);
    if( iPhoneVolume > -1)
        {
        DoStart( iPhoneVolume );
        }
    }

// -----------------------------------------------------------------------------
// CBTRCCVolumeLevelControllerBase::Stop
// -----------------------------------------------------------------------------
//
void CBTRCCVolumeLevelControllerBase::Stop() 
    {
    TRACE_FUNC
    iBtrccActive->Cancel();
    DoStop(); 
    }

// -----------------------------------------------------------------------------
// CBTRCCVolumeLevelControllerBase::Reset
// -----------------------------------------------------------------------------
//
void CBTRCCVolumeLevelControllerBase::Reset()
    {
    TRACE_FUNC 
    iBtrccActive->Cancel();
    DoReset(); 
    }

// -----------------------------------------------------------------------------
// CBTRCCVolumeLevelControllerBase::RegisterVolumeChangeNotification
// -----------------------------------------------------------------------------
//
void CBTRCCVolumeLevelControllerBase::RegisterVolumeChangeNotification() 
    {
    TRACE_FUNC
    return;
    }

// -----------------------------------------------------------------------------
// CBTRCCVolumeLevelControllerBase::GetLocalMaxVolumeL
// -----------------------------------------------------------------------------
//
TInt CBTRCCVolumeLevelControllerBase::GetLocalMaxVolumeL() 
    {
    TRACE_FUNC
    // fetch max volume from adaptation and cache it.
    CMMFDevSound* devSound = CMMFDevSound::NewL();
    iLocalMaxVolume = devSound->MaxVolume();
    TRACE_INFO((_L("Maximum volume is %d"), iLocalMaxVolume))
    delete devSound; // This is not needed for anything else.
    if( iLocalMaxVolume <= 0 )
        {
        TRACE_INFO((_L("Error, Maximum volume value is invalid")))
        User::Leave(KErrNotSupported);
        }
    return iLocalMaxVolume; 
    }

// -----------------------------------------------------------------------------
// CBTRCCVolumeLevelControllerBase::AccessoryChangedVolume
// -----------------------------------------------------------------------------
//
void CBTRCCVolumeLevelControllerBase::AccessoryChangedVolume(TInt aVolumeInPhoneScale) 
    {
    TRACE_FUNC
    iRemoteVolume = aVolumeInPhoneScale;
    TInt vol;
    TInt err = GetPhoneVolume(vol);
    ScalePhoneVolume(iPhoneVolume);
    if(!err)
        {
        TInt prevPhVol = iPhoneVolume;
        iPhoneVolume = vol;
        TInt remoteVol = RoundRemoteVolume(prevPhVol);
        SetPhoneVolume(remoteVol);
        }
    }

// -----------------------------------------------------------------------------
// CBTRCCVolumeLevelControllerBase::SetPhoneVolume
// -----------------------------------------------------------------------------
//
void CBTRCCVolumeLevelControllerBase::SetPhoneVolume(TInt aRemoteVol)
    {
    TRACE_FUNC
    TRACE_INFO((_L("Remote Volume = %d, iPhoneVolume = %d"), aRemoteVol, iPhoneVolume))
    TInt err( KErrNotFound );
    if (aRemoteVol != iPhoneVolume)
        {
        TInt event = (aRemoteVol > iPhoneVolume) ? KPSVolumeUpClicked : KPSVolumeDownClicked;
        err = iVolKeyEventProperty.Set(event);
        TRACE_INFO((_L("Set KMediaKeysVolumeKeyEvent click %d err %d"), event, err));
        }    
    iState = err ? ESubscribePhoneVolume : ESetPhoneVolume;
    }

// -----------------------------------------------------------------------------
// CBTRCCVolumeLevelControllerBase::GetPhoneVolume
// -----------------------------------------------------------------------------
//
TInt CBTRCCVolumeLevelControllerBase::GetPhoneVolume(TInt &aVol)
    {
    aVol = -1;
    TInt err = iVolLevelProperty.Get(aVol);
    TRACE_INFO((_L("Get volume P&S ret %d vol %d"), err, aVol))
    return err;
    }

// -----------------------------------------------------------------------------
// CBTRCCVolumeLevelControllerBase::GetCurrentLocalVolume
// -----------------------------------------------------------------------------
//
TInt CBTRCCVolumeLevelControllerBase::GetCurrentLocalVolume()
    {
    return iPhoneVolume;
    }

// -----------------------------------------------------------------------------
// CBTRCCVolumeLevelControllerBase::GetCurrentRemoteVolume
// -----------------------------------------------------------------------------
//
TInt CBTRCCVolumeLevelControllerBase::GetCurrentRemoteVolume()
    {
    return iRemoteVolume;
    }

// -----------------------------------------------------------------------------
// CBTRCCVolumeLevelControllerBase::RoundRemoteVolume
// -----------------------------------------------------------------------------
//
TInt CBTRCCVolumeLevelControllerBase::RoundRemoteVolume(TInt /*aPrevPhVol*/)
    {
    TRACE_FUNC
    // default implementation
    return iRemoteVolume;
    }

// -----------------------------------------------------------------------------
// CBTRCCVolumeLevelControllerBase::ScalePhoneVolume
// -----------------------------------------------------------------------------
//
void CBTRCCVolumeLevelControllerBase::ScalePhoneVolume(TInt& /*aVolume*/)
    {
    TRACE_FUNC
    // default implementation
    }

// -----------------------------------------------------------------------------
// CBTRCCVolumeLevelControllerBase::RequestCompletedL
// -----------------------------------------------------------------------------
//
void CBTRCCVolumeLevelControllerBase::RequestCompletedL(CBTRCCActive& aActive, TInt aErr)
    {
    TRACE_FUNC
    if(aActive.ServiceId() == KVolumeChangeListenerServiceId)
        {
        TInt prevPhVol = iPhoneVolume;
        TInt err = GetPhoneVolume(iPhoneVolume);
        ScalePhoneVolume(iPhoneVolume);
                
        if(!err && !aErr && iPhoneVolume > -1)
            {
            switch(iState)
                {
                case ESubscribePhoneVolume:
                    // Tell the specialization of the new volume level. 
                    AdjustRemoteVolume(iPhoneVolume); 
                    break;
                case ESetPhoneVolume:
                    TInt remoteVol = RoundRemoteVolume(prevPhVol);
                    SetPhoneVolume(remoteVol);
                    break;
                }
            }
        
        iVolLevelProperty.Subscribe(iBtrccActive->iStatus);
        iBtrccActive->GoActive();
        }
    }

// -----------------------------------------------------------------------------
// CBTRCCVolumeLevelControllerBase::CancelRequest
// -----------------------------------------------------------------------------
//
void CBTRCCVolumeLevelControllerBase::CancelRequest(TInt aServiceId) 
    {
    TRACE_FUNC
    switch (aServiceId)
        {
        case KVolumeChangeListenerServiceId:
            {
            iVolLevelProperty.Cancel();
            break;
            }
        default:
            break;
        } 
    }

void CBTRCCVolumeLevelControllerBase::VolumeControlError(TInt aError) 
    {
    iObserver.VolumeControlError(aError); 
    }


//  End of File  
