bluetoothappprofiles/avrcp/playerinformation/src/playercapabilities.cpp
changeset 0 f63038272f30
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetoothappprofiles/avrcp/playerinformation/src/playercapabilities.cpp	Mon Jan 18 20:28:57 2010 +0200
@@ -0,0 +1,274 @@
+// 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:
+// This file contains the capabilites part of playerinformation.
+// 
+//
+
+/**
+ @file
+ @publishedAll
+ @released
+*/
+
+#include <bluetooth/logger.h>
+#include <remconinterfaceselector.h>
+#include <remcon/avrcpspec.h>
+#include <playerinformationtarget.h>
+
+#include "eventsmask.h"
+#include "playerinformation.h"
+
+#ifdef __FLOG_ACTIVE
+_LIT8(KLogComponent, LOG_COMPONENT_AVRCP_PLAYER_INFO);
+#endif
+
+class TRemConMetadataTransferGetCapabilities 
+	{
+public:
+	TUint8	 				iCapabilityID;
+	};
+
+EXPORT_C void MPlayerCapabilitiesObserver::ClearEvents()
+	{
+	DoClearEvents();
+	}
+
+EXPORT_C TInt MPlayerCapabilitiesObserver::AddEvent(TRegisterNotificationEvent aEvent)
+	{
+	return DoAddEvent(aEvent);
+	}
+	
+EXPORT_C TInt MPlayerCapabilitiesObserver::RemoveEvent(TRegisterNotificationEvent aEvent)
+	{
+	return DoRemoveEvent(aEvent);
+	}
+
+EXPORT_C void MPlayerCapabilitiesObserver::ClearCompanyIds()
+	{
+	DoClearCompanyIds();
+	}
+
+EXPORT_C TInt MPlayerCapabilitiesObserver::AddCompanyId(TInt aID)
+	{
+	return DoAddCompanyId( aID );
+	}
+
+EXPORT_C TInt MPlayerCapabilitiesObserver::RemoveCompanyID(TInt aID)
+	{
+	return DoRemoveCompanyID( aID );
+	}
+
+
+// from MPlayerCapabilitiesObserver
+void CPlayerInfoTarget::DoClearEvents()
+	{
+	// AVRCP 1.3 specification, Appendix H says that PlaybackStatusChanged
+	// and TrackChanged event notification support is mandatory, so add these
+	
+	iSupportedNotificationEventList->Reset();
+	iSupportedNotificationEventList->Append(ERegisterNotificationPlaybackStatusChanged);
+	iSupportedNotificationEventList->Append(ERegisterNotificationTrackChanged);
+	}
+
+
+TInt CPlayerInfoTarget::DoAddEvent( TRegisterNotificationEvent aEvent )
+	{
+	// check the event is supported (note system status is NOT supported)
+	if (   aEvent >= ERegisterNotificationReservedLast
+		|| aEvent == ERegisterNotificationSystemStatusChanged_NotSupported)
+		{
+		return KErrNotSupported;
+		}
+		
+	// check if aEvent is already in the list of supported events
+	if (!iSupportedNotificationEventList->Find(aEvent))
+		{
+		// not found so add it to the list
+		iSupportedNotificationEventList->Append(aEvent);
+		return KErrNone;
+		}
+	
+	// else return already in the list
+	return KErrAlreadyExists;
+	}
+
+
+TInt CPlayerInfoTarget::DoRemoveEvent( TRegisterNotificationEvent aEvent )
+	{
+	// AVRCP 1.3 specification, Appendix H says that PlaybackStatusChanged
+	// and TrackChanged event notification support is mandatory, so add these
+	TInt err = KErrNone;
+	if (   aEvent == ERegisterNotificationPlaybackStatusChanged
+		|| aEvent == ERegisterNotificationTrackChanged)
+		{
+		return KErrNotSupported;
+		}
+	
+	// Find aEvent in the list of supported events
+	if (iSupportedNotificationEventList->Find(aEvent))
+		{
+		// and then remove it
+		iSupportedNotificationEventList->Remove(aEvent);
+		TInt pendingPos = iPendingNotificationEventList.Find(aEvent);
+		if (pendingPos != KErrNotFound)
+			{
+			iPendingNotificationEventList.Remove( pendingPos );
+			
+			// Tell anyone waiting for a notification that an event has been
+			// removed. Alas, we can't specify _WHICH_ event has been removed
+			// since there's no way to indicate this in an INTERNAL_ERROR response
+			SendError(KErrAvrcpMetadataInternalError, 
+					  RAvrcpIPC::SetIPCOperationIdFromEventId(aEvent), 
+					  ERemConNotifyResponseChanged);
+			}
+		}
+	else
+		{
+		err = KErrNotFound;
+		}
+	return err;
+	}
+
+
+void CPlayerInfoTarget::DoClearCompanyIds()
+	{
+	// The Bluetooth SIG vendor id must always be present
+	// See AVRCP 1.3 Specification, section 5.5.1, table 5.4
+	iCompanyIdList.Reset();
+	iCompanyIdList.Append(KBluetoothSIGVendorId);
+	}
+
+
+TInt CPlayerInfoTarget::DoAddCompanyId( TInt aID )
+	{
+	if ( aID > KMaxCompanyID )
+		{
+		return KErrNotSupported;
+		}
+		
+	// check if the ID is already in the list
+	TInt pos = iCompanyIdList.Find( aID );
+
+	// add only if not present in list to avoid duplicates
+	if (pos != KErrNotFound)
+		{
+		return KErrAlreadyExists;
+		}
+	
+	// make sure the list cannot contain more than 255 items
+	if (iCompanyIdList.Count() >= KMaxNrOfCompanyIDs)
+		{
+		return KErrOverflow;
+		}
+		
+	return iCompanyIdList.Append( aID );
+	}
+
+
+TInt CPlayerInfoTarget::DoRemoveCompanyID( TInt aID )
+	{
+	// The Bluetooth SIG vendor id must always be present
+	// See AVRCP 1.3 Specification, section 5.5.1, table 5.4
+	if ( aID == KBluetoothSIGVendorId )
+		{
+		return KErrNotSupported;
+		}
+		
+	// check if the ID is in the list
+	TInt pos = iCompanyIdList.Find( aID );
+
+	// if found remove else do nothing
+	if (pos != KErrNotFound)
+		{
+		iCompanyIdList.Remove( pos );
+		return KErrNone;
+		}
+	return pos;
+	}
+
+
+void CPlayerInfoTarget::ProcessGetCapabilities(const TDesC8& aData)
+	{
+	LOG_STATIC_FUNC
+
+	/* Decode the get capability message */
+	TRemConMetadataTransferGetCapabilities getCapability;
+	
+	// check there is at least 1 byte of data
+	if (!aData.Length())
+		{
+		// Invalid packet
+		return SendError(KErrAvrcpMetadataInvalidParameter, EGetCapabilities);
+		}
+		
+	TPckgC<TRemConMetadataTransferGetCapabilities> data(*reinterpret_cast<const TRemConMetadataTransferGetCapabilities*>(aData.Ptr()));
+	getCapability = data();
+	TGetCapabilityValues id = (TGetCapabilityValues) getCapability.iCapabilityID;
+	
+	// format the response in a TRemConGetCapabilitiesResponse
+	RRemConGetCapabilitiesResponse response;
+
+	switch ( id )
+		{
+	case ECapabilityIdCompanyID:
+		// respond with ECapabilityIdCompanyID
+		response.iCapabilityId = ECapabilityIdCompanyID;
+
+		// followed by number of IDs
+		response.iCapabilityCount = iCompanyIdList.Count();
+
+		// and then list of company ids,
+		for (TInt i=0; i< iCompanyIdList.Count(); i++ )
+			{
+			TInt x = iCompanyIdList[i];
+			if (response.iCapabilities.Append(x) != KErrNone)
+				{
+				response.Close();
+				return SendError(KErrAvrcpMetadataInternalError, EGetCapabilities);   // Try to send internal error if OOM
+				}
+			}
+		break;
+		
+	case ECapabilityIdEventsSupported:
+		// respond with ECapabilityIdEventsSupported
+		response.iCapabilityId = ECapabilityIdEventsSupported;
+		
+		// followed by number of supported events, and then list of events
+		response.iCapabilityCount = 0;
+		iSupportedNotificationEventList->Begin();
+		while(iSupportedNotificationEventList->Next())
+			{
+			if (KErrNone != response.iCapabilities.Append(iSupportedNotificationEventList->Get()))
+				{
+				response.Close();
+				return SendError(KErrAvrcpMetadataInternalError, EGetCapabilities);   // Try to send internal error if OOM
+				}
+			response.iCapabilityCount++;
+			}
+		break;	
+		
+	default:
+		/* other IDs are reserved */
+		return SendError(KErrAvrcpMetadataInvalidParameter, EGetCapabilities);  // Invalid packet
+		}
+
+	TInt error = 0;
+	TRAP(error, response.WriteL(iOutBuf));   // Don't send error if OOM
+	response.Close();
+	if (error == KErrNone)
+		// send the result back to the CT
+		InterfaceSelector().SendUnreliable(TUid::Uid(KRemConPlayerInformationUid),
+											EGetCapabilities, ERemConResponse, iOutBuf );
+	}
+