bluetoothappprofiles/avrcp/remconbeareravrcp/src/playerstatewatcher.cpp
author Pat Downey <patd@symbian.org>
Wed, 01 Sep 2010 12:20:04 +0100
branchRCL_3
changeset 56 9386f31cc85b
parent 55 613943a21004
permissions -rw-r--r--
Revert incorrect RCL_3 drop: Revision: 201033 Kit: 201035

// Copyright (c) 2008-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:
//

#include "mediabrowse.h"
#include "avrcputils.h"
#include "commandhandlerinterface.h"
#include "internalcommand.h"
#include "mediabrowse.h"
#include "playerstatewatcher.h"
#include "remconcommandinterface.h"
#include "avrcplog.h"
#include "playerinformation.h"

CPlayerWatcherBase::CPlayerWatcherBase(MRemConCommandInterface& aCommandInterface)
	: iCommandInterface(aCommandInterface), iCommands()
	{
	LOG_FUNC;
	}

CPlayerWatcherBase::~CPlayerWatcherBase()
	{
	LOG_FUNC;
	}

void CPlayerWatcherBase::StopWatchingPlayer(TRemConClientId aClientId)
	{
	LOG_FUNC;
	CInternalCommand* command = *iCommands.Find(aClientId);
	__ASSERT_DEBUG(command, AVRCP_PANIC(ENotWatchingPlayer));

	TUint transId = command->RemConCommandId();
	iCommandInterface.MrcciCommandExpired(transId);

	iCommands.Remove(aClientId);
	command->DecrementUsers();
	}

void CPlayerWatcherBase::MessageSent(CAvrcpCommand& /*aCommand*/, TInt /*aSendResult*/)
	{
	LOG_FUNC;
	__DEBUG_ONLY(AVRCP_PANIC(ELowerInterfaceUsedOnInternalHandler));
	}

void CPlayerWatcherBase::MaxPacketSize(TInt /*aMtu*/)
	{
	LOG_FUNC;
	__DEBUG_ONLY(AVRCP_PANIC(ELowerInterfaceUsedOnInternalHandler));
	}

void CPlayerWatcherBase::ReceiveCommandL(const TDesC8& /*aMessageInformation*/, SymbianAvctp::TTransactionLabel /*aTransLabel*/, const TBTDevAddr& /*aAddr*/)
	{
	LOG_FUNC;
	__DEBUG_ONLY(AVRCP_PANIC(ELowerInterfaceUsedOnInternalHandler));
	}

CInternalCommand& CPlayerWatcherBase::FindCommand(TUid __DEBUG_ONLY(aInterfaceUid),
		TUint aTransactionId, TRemConClientId& aFoundClientId)
	{
	__ASSERT_DEBUG(aInterfaceUid == TUid::Uid(KRemConPlayerInformationUid) || aInterfaceUid == TUid::Uid(KRemConMediaBrowseApiUid), AVRCP_PANIC(EResponseForWrongInterface));
	THashMapIter<TRemConClientId, CInternalCommand*> commandIter(iCommands);

	CInternalCommand* command = NULL;
	while(commandIter.NextValue())
		{
		command = *commandIter.CurrentValue();
		if(command->RemConCommandId() == aTransactionId)
			{
			aFoundClientId = *commandIter.CurrentKey();
			break;
			}
		}

	// If command is NULL we reached the end of our iter without finding the match
	__ASSERT_DEBUG(command, AVRCP_PANIC(EUnmatchedResponseFromRemCon));

	return *command;
	}

TInt CPlayerWatcherBase::SendRemConResponse(TUid aInterfaceUid, TUint aTransactionId, RBuf8& aData)
	{
	LOG_FUNC;

	TRemConClientId clientId;
	CInternalCommand& command = FindCommand(aInterfaceUid, aTransactionId, clientId);

	ReceiveUpdate(command, clientId, aData);

	return KErrNone;
	}

void CPlayerWatcherBase::SendReject(TUid aInterfaceUid, TUint aTransactionId)
	{
	TRemConClientId clientId;
	(void)FindCommand(aInterfaceUid, aTransactionId, clientId);

	ReceiveReject(clientId);
	}

void CPlayerWatcherBase::Disconnect()
	{
	LOG_FUNC;
	}

CPlayStatusWatcher* CPlayStatusWatcher::NewL(MPlayStatusObserver& aObserver, MRemConCommandInterface& aCommandInterface)
	{
	LOG_STATIC_FUNC;
	CPlayStatusWatcher* watcher = new(ELeave)CPlayStatusWatcher(aObserver, aCommandInterface);
	return watcher;
	}

CPlayStatusWatcher::CPlayStatusWatcher(MPlayStatusObserver& aObserver,
		MRemConCommandInterface& aCommandInterface)
	: CPlayerWatcherBase(aCommandInterface), iObserver(aObserver)
	{
	LOG_FUNC;
	}

CPlayStatusWatcher::~CPlayStatusWatcher()
	{
	LOG_FUNC;
	}

void CPlayStatusWatcher::StartWatchingPlayerL(TRemConClientId aClientId)
	{
	LOG_FUNC;
	__ASSERT_DEBUG(!iCommands.Find(aClientId), AVRCP_PANIC(EAlreadyWatchingPlayer));

	CInternalCommand* command = CInternalCommand::NewL(TUid::Uid(KRemConPlayerInformationUid),
			0,
			EGetPlayStatusUpdate,
			KNullDesC8);

	CleanupStack::PushL(command);
	iCommands.InsertL(aClientId, command);
	CleanupStack::Pop(command);
	command->IncrementUsers();

	// Initially request uid notification relative to stopped
	SendPlayStatusUpdateRequest(*command, aClientId, MPlayerEventsObserver::EStopped);
	}

void CPlayStatusWatcher::SendPlayStatusUpdateRequest(CInternalCommand& aCommand, TRemConClientId& aClientId, MPlayerEventsObserver::TPlaybackStatus aPlaybackStatus)
	{
	LOG_FUNC;

	RRemConPlayerInformationGetPlayStatusUpdateRequest request;
	request.iStatus = aPlaybackStatus;

	TBuf8<sizeof(MPlayerEventsObserver::TPlaybackStatus)> buf;
	TRAPD(err, request.WriteL(buf));

	// We know how big the request is so this should never fail
	__ASSERT_DEBUG(err == KErrNone, AVRCP_PANIC(EUidUpdateRequestWriteFailure));

	TUint transId = iCommandInterface.MrcciNewTransactionId();
	TRAP(err, aCommand.ResetL(transId, buf));

	if(err == KErrNone)
		{
		iCommandInterface.MrcciNewCommand(aCommand, aClientId);
		}
	else
		{
		// Doom
		iObserver.MpsoError(aClientId);
		}
	}

void CPlayStatusWatcher::ReceiveUpdate(CInternalCommand& aCommand, TRemConClientId aClientId, RBuf8& aData)
	{
	LOG_FUNC;

	// Read 4 byte Big-Endian error code before the payload
	RAvrcpIPCError errorResponse;
	TRAPD(err, errorResponse.ReadL(aData));
	err = err ? err : errorResponse.iError;

	RRemConPlayerInformationGetPlayStatusUpdateResponse response;
	if(!err)
		{
		// Parse the rest of the response (minus error code)
		TRAP(err, response.ReadL(aData.RightTPtr(aData.Length() - KLengthErrorResponse)));
		}

	aData.Close(); // data has been used now

	if(!err)
		{
		iObserver.MpsoPlayStatusChanged(aClientId, response.iStatus);
		SendPlayStatusUpdateRequest(aCommand, aClientId, response.iStatus);
		}
	else
		{
		// Should never get here with a valid player.  This client is
		// sending us junk.
		iObserver.MpsoError(aClientId);
		}
	}

void CPlayStatusWatcher::ReceiveReject(TRemConClientId aClientId)
	{
	LOG_FUNC;
	iObserver.MpsoError(aClientId);
	}

CUidWatcher* CUidWatcher::NewL(MUidObserver& aObserver,
		MRemConCommandInterface& aCommandInterface)
	{
	LOG_STATIC_FUNC;
	CUidWatcher* watcher = new(ELeave)CUidWatcher(aObserver, aCommandInterface);
	return watcher;
	}

CUidWatcher::CUidWatcher(MUidObserver& aObserver,
		MRemConCommandInterface& aCommandInterface)
	: CPlayerWatcherBase(aCommandInterface), iObserver(aObserver)
	{
	LOG_FUNC;
	}

CUidWatcher::~CUidWatcher()
	{
	LOG_FUNC;
	}

void CUidWatcher::StartWatchingPlayerL(TRemConClientId aClientId)
	{
	LOG_FUNC;
	__ASSERT_DEBUG(!iCommands.Find(aClientId), AVRCP_PANIC(EAlreadyWatchingPlayer));

	CInternalCommand* command = CInternalCommand::NewL(TUid::Uid(KRemConMediaBrowseApiUid),
			0,
			EMediaLibraryStateCookieUpdateOperationId,
			KNullDesC8);

	CleanupStack::PushL(command);
	iCommands.InsertL(aClientId, command);
	CleanupStack::Pop(command);
	command->IncrementUsers();

	// Initially request uid notification relative to 0 uid counter
	SendUidUpdateRequest(*command, aClientId, 0);
	}

void CUidWatcher::SendUidUpdateRequest(CInternalCommand& aCommand, TRemConClientId& aClientId, TUint16 aUidCounter)
	{
	LOG_FUNC;
	RRemConUidsChangedRequest request;
	request.iInitialUidCounter = aUidCounter;
	TBuf8<sizeof(TUint16)> buf;
	TRAPD(err, request.WriteL(buf));
	// We know how big the request is so this should never fail
	__ASSERT_DEBUG(err == KErrNone, AVRCP_PANIC(EUidUpdateRequestWriteFailure));

	TUint transId = iCommandInterface.MrcciNewTransactionId();
	TRAP(err, aCommand.ResetL(transId, buf));

	if(err == KErrNone)
		{
		iCommandInterface.MrcciNewCommand(aCommand, aClientId);
		}
	else
		{
		// Doom
		iObserver.MuoError(aClientId);
		}
	}

void CUidWatcher::ReceiveUpdate(CInternalCommand& aCommand, TRemConClientId aClientId, RBuf8& aData)
	{
	LOG_FUNC;
	RRemConUidsChangedResponse response;
	TRAPD(err, response.ReadL(aData));
	aData.Close(); // data has been used now

	if(!err)
		{
		iObserver.MuoUidChanged(aClientId, response.iUidCounter);
		SendUidUpdateRequest(aCommand, aClientId, response.iUidCounter);
		}
	else
		{
		// Should never get here with a valid player.  This client is
		// sending us junk.
		iObserver.MuoError(aClientId);
		}
	}

void CUidWatcher::ReceiveReject(TRemConClientId aClientId)
	{
	LOG_FUNC;
	iObserver.MuoError(aClientId);
	}