internetradio2.0/uisrc/irmediaclient.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Mon, 19 Apr 2010 14:01:53 +0300
changeset 0 09774dfdd46b
permissions -rw-r--r--
Revision: 201011 Kit: 201015

/*
* Copyright (c) 2006-2007 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:  ?Description
*
*/


#include <e32property.h>
#include "irpubsubkeys.h"

#include "irctrlcmdobserver.h"
#include "irdebug.h"
#include "irmediaclient.h"
#include "irmediaenginebuffer.h"
#include "irmediaengineinterface.h"
#include "ircontrolparams.h"

const TInt KZeroVolumeLevel = 0;
const TInt KIRBitRateDivider = 8;    // To convert bits to bytes.
const TInt KIRByteMultiplier = 1024; // To convert kilo bytes to bytes.
const TInt KIRValidBitRate = 0;      // Starting point for valid bit rate.
const TInt KIRDefBitRate = 64;       // Default bit rate for buffer size calculation.
const TInt KIRMinBitRate = 8;        // Minimum bit rate for buffer size calculation.
const TInt KIRMaxBitRate = 192;      // Maximum bit rate for buffer size calculation.

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

// ---------------------------------------------------------------------------
// Function : NewL
// Two Phase Constructor - NewL
// ---------------------------------------------------------------------------
//	 
CIRMediaClient* CIRMediaClient::NewL(CIRCtrlCmdObserver* aChannel)
	{
	IRLOG_DEBUG( "CIRMediaClient::NewL - Entering" );
	CIRMediaClient* self = NewLC(aChannel);
    CleanupStack::Pop(self);
    IRLOG_DEBUG( "CIRMediaClient::NewL - Exiting." );
    return self;	
	}
	
// ---------------------------------------------------------------------------
// Function : NewLC
// Two Phase Constructor - NewLC
// ---------------------------------------------------------------------------
//
CIRMediaClient* CIRMediaClient::NewLC(CIRCtrlCmdObserver* aChannel)
	{
	IRLOG_DEBUG( "CIRMediaClient::NewLC - Entering" );
	CIRMediaClient* self = new (ELeave) CIRMediaClient();
    CleanupStack::PushL(self);
    self->ConstructL(aChannel);
	IRLOG_DEBUG( "CIRMediaClient::NewLC - Exiting." );
    return self;	
	}

// ---------------------------------------------------------------------------
// destructor function
// destructor of the player component
// ---------------------------------------------------------------------------
//
CIRMediaClient::~CIRMediaClient()
    {
	IRLOG_DEBUG( "CIRMediaClient::~CIRMediaClient - Entering" );
	//deletes the player
	delete iPlayer;
	//deletes the buffers associated with player
	delete[] iTempBuffer;
	delete[] iCurrentBuffer;
	IRLOG_DEBUG( "CIRMediaClient::~CIRMediaClient - Exiting." );
    }
    	
// ---------------------------------------------------------------------------
// This is default Constructor
// for the class CIRMediaClient
// ---------------------------------------------------------------------------
//	
CIRMediaClient::CIRMediaClient():iInputBuffer(NULL,0,0) 
	{
	IRLOG_DEBUG( "CIRMediaClient::CIRMediaClient" );
	}

// ---------------------------------------------------------------------------
// Two phase ConstructL
// network component is taken as input
// ---------------------------------------------------------------------------
//
void CIRMediaClient::ConstructL(CIRCtrlCmdObserver* aChannel)
    {
	IRLOG_DEBUG( "CIRMediaClient::ConstructL - Entering" );
	iChannel = aChannel;
	IRLOG_DEBUG( "CIRMediaClient::ConstructL - Exiting" );
	}
						
										   //For Play control
										   
// ---------------------------------------------------------------------------
// Function : PlayL
// Starts to play the stream
// ---------------------------------------------------------------------------
//
TInt CIRMediaClient::Play()
	{
	IRLOG_DEBUG( "CIRMediaClient::Play - Entering" );
	IRLOG_DEBUG( "CIRMediaClient::Play - Exiting" );
	//sents a play request to media engine
	if( iPlayer )
		{
		iPlayer->Play();
		IRLOG_DEBUG( "CIRMediaClient::Play - Exiting (1)." );
		return KErrNone;
		}
	else
		{
		IRLOG_DEBUG( "CIRMediaClient::Play - Exiting (2)." );
		return KErrNotFound;
		}	
	}

// ---------------------------------------------------------------------------
// Function : StopL
// Stops to play the stream
// ---------------------------------------------------------------------------
//
void CIRMediaClient::Stop()
	{
	IRLOG_DEBUG( "CIRMediaClient::Stop - Entering" );
	//sents a stop request to media engine
	if( iPlayer )
		{
		iPlayer->Stop();
		}
	else
		{
		iCommand = EStoppedPlaying;
		iChannel->SentRequest(iCommand,KErrNone);
		}
	IRLOG_DEBUG( "CIRMediaClient::Stop - Exiting." );
	}
										
										 //For Volume Control
// ---------------------------------------------------------------------------
// Function : SetVolume
// function to set the volume, 
// ---------------------------------------------------------------------------
//
void CIRMediaClient::SetVolume(TInt aVolume )
	{
	IRLOG_DEBUG( "CIRMediaClient::SetVolume - Entering" );
	//if player is exists it will set the volume
	if( iPlayer )
		{
		iPlayer->SetVolume(aVolume);	
		}		
	IRLOG_DEBUG( "CIRMediaClient::SetVolume - Exiting." );
	}

// ---------------------------------------------------------------------------
// Function : MaxVolume
// ---------------------------------------------------------------------------
//	
TInt CIRMediaClient::MaxVolume() const
	{
	IRLOG_DEBUG( "CIRMediaClient::MaxVolume - Entering" );
	IRLOG_DEBUG( "CIRMediaClient::MaxVolume - Exiting" );
	//if player is created it will sent the max volume else return zero instead of MaxVolume
	if( iPlayer )
		{
		IRLOG_DEBUG( "CIRMediaClient::MaxVolume - Exiting (1)." );
		//returns maximum volume if player exists
		return iPlayer->MaxVolume();	
		}		
	else
		{
		//else zero is returned
		IRLOG_DEBUG( "CIRMediaClient::MaxVolume - Exiting (2)." );
		return KZeroVolumeLevel;	
		}
	}

// ---------------------------------------------------------------------------
// Function : Volume
// function to returns the volume
// ---------------------------------------------------------------------------
//		
TInt CIRMediaClient::Volume() const
	{
	IRLOG_DEBUG( "CIRMediaClient::Volume - Entering" );
	IRLOG_DEBUG( "CIRMediaClient::Volume - Exiting" );
	//if player is created it will sent the volume else return zero instead of Volume
	if( iPlayer )
		{
		//if player exist it returns the current volume
		IRLOG_DEBUG( "CIRMediaClient::Volume - Exiting (1)." );
		return iPlayer->Volume();	
		}		
	else
		{
		//else will return negative volume
		IRLOG_DEBUG( "CIRMediaClient::Volume - Exiting (2)." );
		return KZeroVolumeLevel;	
		}
	}

// ---------------------------------------------------------------------------
// Function: BufferFilled
// Set the whether a Fill Buffer is currently active
// ---------------------------------------------------------------------------
//
void CIRMediaClient::BufferFilled()
	{
	IRLOG_DEBUG( "CIRMediaClient::BufferFilled - Entering" );
	if( iFirstTime )
		{
		//First all the buffers are filled
		iInputBufferPtr += iConfig.iPlayBufferSize;	
		if( (iInputBufferPtr + iConfig.iPlayBufferSize) <= 
			(iTempBuffer + iConfig.iPlayBufferCount*iConfig.iPlayBufferSize) )
			{
			//buffer is not completely filled
			iInputBuffer.Set(iInputBufferPtr,iConfig.iPlayBufferSize,iConfig.iPlayBufferSize);	
			
			if( iStopBuffering )
				{
				//if iStopBuffering is true we won't continue in this loop
				return;		
				}			
			else // if not stop buffering is called
				{
				//fills the buffer and sents the buffer percentage
				iChannel->FilltheBuffer(iInputBuffer);			
				}				
			}
		else
			{
			//buffer is completely filled
			iFirstTime = EFalse;
			iNewPlayer = EFalse;
			if( iStopBuffering )
				{
				//if stop buffering is true we will not proceed further
				return;	
				}
			else
				{
                // Error reporting done inside CreatePlayer
				if ( CreatePlayer() )
				    {
				    // Sending this event causes NowPlayingView activation
				    iBufferPercentage = K100Percentage;				
				    iChannel->SentRequest( EBufferFillStop, iBufferPercentage );	
				
				    //player has already buffered completely for the first time
				    //so even if StopInitialBuffering is called media client is help less
				    //to handle this situation iStopBuffering is made ETrue
				    iStopBuffering = ETrue;

				    //called for intializing a new player
				    InitializePlayer( iConfig,iChannel );
				
				    //calls play for the first time
				    iPlayer->Play();
				    }
				}									
			}
		}
	else
		{
		//buffer is already filled for first time
		//media engine is created and playing so Buffer filled 
		//function of media Engine should be called
		iPlayer->BufferFilled();				
		}			
	IRLOG_DEBUG( "CIRMediaClient::BufferFilled - Exiting." );
	}
	
// ---------------------------------------------------------------------------
// Function: StartNewPlayerL
// Set the whether a Fill Buffer is currently active
// ---------------------------------------------------------------------------
//
void CIRMediaClient::StartNewPlayerL(TConfig& aConfig,const TDesC8& aFormat
	)
	{
	IRLOG_DEBUG( "CIRMediaClient::StartNewPlayerL - Entering" );
	//format is copied
	iFormat.Copy(aFormat);

	//stop of intial buffering from media client is enable
	iStopBuffering = EFalse;
	
	iConfig = aConfig;

	TInt bitRate(0);
	RProperty::Get ( KUidActiveInternetRadioApp, KIRPSBitrate, bitRate );
    // Next line will round the bitrate down to be divisible by KIRBitRateDivider.
	bitRate = bitRate - (bitRate % KIRBitRateDivider);
	if( bitRate <= KIRValidBitRate )
	    {
	    // If invalid bit rate info, use default bit rate for calculating buffer sizes.
	    bitRate = KIRDefBitRate;
	    }
	else if( bitRate < KIRMinBitRate )
	    {
	    // If small bit rate info, use minimum bit rate for calculating buffer sizes.
	    // To make single buffer minimum size 1 kB.
	    bitRate = KIRMinBitRate;
	    }
	else if( bitRate > KIRMaxBitRate )
	    {
	    // If large bit rate info, use maximum bit rate for calculating buffer sizes.
	    // To make single buffer maximum size 24 kB.
	    bitRate = KIRMaxBitRate;
	    }
	else
	    {
	    }
	iConfig.iPlayBufferCount = KIRInputBufferCount;
    iConfig.iPlayBufferSize = KIRByteMultiplier*bitRate/KIRBitRateDivider;
	
	//creates a new instance of media buffer for new player
	iTempBuffer = new (ELeave) TUint8[iConfig.iPlayBufferCount*iConfig.iPlayBufferSize];
	iInputBufferPtr = iTempBuffer;

	//initial buffering starts
	iInputBuffer.Set(iInputBufferPtr,iConfig.iPlayBufferSize,iConfig.iPlayBufferSize);
	iNewPlayer = ETrue;
	iFirstTime = ETrue;

	//initial buffering starts
	iChannel->FilltheBuffer(iInputBuffer);	
	
	//starts audio fade out for the previous channel
	IRLOG_DEBUG( "CIRMediaClient::StartNewPlayerL - Exiting." );
	}

// ---------------------------------------------------------------------------
// Function: StopMediaBuffering
// stops buffering of media engine, the change cannot be reverted 
// ---------------------------------------------------------------------------
//
void CIRMediaClient::StopMediaBuffering()
	{
	IRLOG_DEBUG( "CIRMediaClient::StopMediaBuffering - Entering" );
	//calls media engine's stop buffering cancels the buffering in media engine
	if( iPlayer )
		{
		iPlayer->StopPlayerBuffering();	
		}			
	IRLOG_DEBUG( "CIRMediaClient::StopMediaBuffering - Exiting." );
	}

// ---------------------------------------------------------------------------
// Function: StopInitialBuffering
// stops buffering from media client, media engine is not stopped 
// ---------------------------------------------------------------------------
//
void CIRMediaClient::StopInitialBuffering()
	{
	IRLOG_DEBUG( "CIRMediaClient::StopInitialBuffering - Entering" );
	//initially buffering is taken care by media client and then 
	//it shift the responsibility to media engine
	//this is done because audio fade out has to take place when other channel buffers
	//if media client is handling the buffer it should be stopped
	//media client is handling the buffering
	iStopBuffering = ETrue;
	
	delete[] iTempBuffer;
	iTempBuffer = NULL;
	
	iCommand=EStereo;
	iChannel->SentRequest(iCommand,KErrNone);
	delete iPlayer;
	iPlayer = NULL;
	
	iStopBuffering = ETrue;
	//return true to indicate success of cancelling of buffer
	IRLOG_DEBUG( "CIRMediaClient::StopInitialBuffering - Exiting." );
	}

// ---------------------------------------------------------------------------
// Function: SetCodecSettings
// Creates an instance of the players and initialize it
// ---------------------------------------------------------------------------
//
TBool CIRMediaClient::CreatePlayer()
	{
    IRLOG_DEBUG( "CIRMediaClient::CreatePlayer" );
    TBool createResult( ETrue );
	//delete the instance of previously created player
	iCommand=EStereo;
	iChannel->SentRequest(iCommand,KErrNone);
    if ( iPlayer )
    	{
    	delete iPlayer;
    	iPlayer = NULL;
    	}
		
	//media engine's instance is created type is stored in iFormat (basically the mime type)
	TRAPD(error,iPlayer = CIRMediaEngineInterface::NewL(iFormat));
    if( error )
        {
        iChannel->SentRequest( EError, KIRCtrlCmdPlayerNotCreated );
        createResult = EFalse;
        }
    
    return createResult;    
	}
// ---------------------------------------------------------------------------
// CIRMediaClient::InitializePlayer
// ---------------------------------------------------------------------------
//
void CIRMediaClient::InitializePlayer( TConfig& aConfig,
	CIRCtrlCmdObserver* aChannel)
	{
	IRLOG_DEBUG( "CIRMediaClient::SetCodecSettings" );

	//delete the instance of buffer associated with previously playing player
	delete[] iCurrentBuffer;
	iCurrentBuffer = NULL;
	
	//current buffer is made same as previous buffer
	iCurrentBuffer = iTempBuffer;
	iTempBuffer = NULL;
		
	//intialize the media engine
	iPlayer->Intialize(aConfig,iCurrentBuffer,aChannel);
	IRLOG_DEBUG( "CIRMediaClient::SetCodecSettings - Exiting." );
	}

// ---------------------------------------------------------------------------
// CIRNowPlayingWrapper::GetMediaClientInstance()
// Returns the Audio Player Instance
// ---------------------------------------------------------------------------
//
CMdaAudioOutputStream* CIRMediaClient::GetPlayerInstance()
	{
	IRLOG_DEBUG( "CIRMediaClient::GetMediaClientInstance " );
	return (iPlayer->GetAudioPlayer());	
	}