remotecontrol/avrcp/playerinformation/src/playerinformation.cpp
changeset 51 20ac952a623c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/remotecontrol/avrcp/playerinformation/src/playerinformation.cpp	Wed Oct 13 16:20:29 2010 +0300
@@ -0,0 +1,293 @@
+// 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:
+//
+
+/**
+ @file
+ @publishedAll
+ @released
+*/
+
+#include <bluetooth/logger.h>
+#include <playerinformationtarget.h>
+#include <e32property.h> 
+#include <hwrmpowerstatesdkpskeys.h>
+
+#include "playerapplicationsetting.h"
+#include "eventsmask.h"
+#include "playerinformation.h"
+
+#ifdef __FLOG_ACTIVE
+_LIT8(KLogComponent, LOG_COMPONENT_AVRCP_PLAYER_INFO);
+#endif
+
+EXPORT_C CPlayerInfoTarget* CPlayerInfoTarget::NewL(CRemConInterfaceSelector& aInterfaceSelector,
+										MPlayerCapabilitiesObserver*& aPlayerCapabilitiesObserver,
+										MPlayerApplicationSettingsObserver*& aPlayerApplicationSettingsObserver,
+										MPlayerEventsObserver*& aPlayerEventsObserver,
+										MPlayerApplicationSettingsNotify& aApplicationSettingNotifier )
+	{
+	LOG_STATIC_FUNC
+
+	CPlayerInfoTarget* self = new(ELeave) CPlayerInfoTarget(aInterfaceSelector, aApplicationSettingNotifier);
+	CleanupStack::PushL(self);
+	self->ConstructL( aPlayerCapabilitiesObserver, aPlayerApplicationSettingsObserver, aPlayerEventsObserver );
+	CleanupStack::Pop(self);
+	return self;
+	}
+	
+/** 
+Constructs this interface.
+@param aInterfaceSelector An interface selector for use with this interface.
+@internalComponent
+@released
+*/
+CPlayerInfoTarget::CPlayerInfoTarget(CRemConInterfaceSelector& aInterfaceSelector, MPlayerApplicationSettingsNotify& aApplicationSettingNotifier)
+:	CRemConInterfaceBase(TUid::Uid(KRemConPlayerInformationUid), 
+						 KMaxLengthPlayerInformationMsg,
+						 aInterfaceSelector,
+						 ERemConClientTypeTarget),
+	iApplicationSettingNotifier(aApplicationSettingNotifier),
+	iPlaybackStatusUpdatePending(EFalse)
+	{
+	}
+	
+		
+void CPlayerInfoTarget::ConstructL(MPlayerCapabilitiesObserver*& aPlayerCapabilitiesObserver,
+										MPlayerApplicationSettingsObserver*& aPlayerApplicationSettingsObserver,
+										MPlayerEventsObserver*& aPlayerEventsObserver )
+	{
+	// reserve two AV/C frames, for this reasoning:
+	// GetCapabilities (PDU 0x10) can generate a response
+	// which is (255 * 3 bytes) + 2 bytes = 767 total and
+	// will fit into two AVC frames. Other PDUs generate
+	// less than this, except for PDUs 0x15 and 0x16 which
+	// use their own buffer pre-allocated by calling Size()
+	iOutBuf.CreateL(KAVCFrameMaxLength * 2);
+	
+	BaseConstructL();
+	
+	aPlayerCapabilitiesObserver = this;
+	aPlayerApplicationSettingsObserver = this;
+	aPlayerEventsObserver = this;
+	
+	// default values for event notifiers
+	iPlayBackStatus = EStopped;
+	
+	// If no track currently selected
+	iTrackId = KNoTrackSelected;
+	
+	iLengthInMilliseconds = 0;
+	iTrackPosition = EStart;
+	
+	// If no track currently selected, then return KPlaybackPositionUnknown
+	iPlaybackPositionInMilliseconds = KPlaybackPositionUnknown;
+	iLastNotifiedPlaybackPositionInMilliseconds	= KPlaybackPositionUnknown;
+
+	// The time interval used for playback position notification
+	iPlayBackIntervalInMilliseconds = 0;
+
+	// Try to detect battery status from hardware P&S properties	
+	iBatteryStatus = DetectBatteryStatus();
+
+	// The Bluetooth SIG vendor id must always be present
+	// See AVRCP 1.3 Specification, section 5.5.1, table 5.4
+	iCompanyIdList.AppendL(KBluetoothSIGVendorId);
+ 
+	// AVRCP 1.3 specification, Appendix H says that PlaybackStatusChanged
+	// and TrackChanged event notification support is mandatory, so add these
+	iSupportedNotificationEventList = new (ELeave) TEventsMask();
+	iSupportedNotificationEventList->Append(ERegisterNotificationPlaybackStatusChanged);
+	iSupportedNotificationEventList->Append(ERegisterNotificationTrackChanged);
+	}
+
+EXPORT_C CPlayerInfoTarget::~CPlayerInfoTarget()
+	{
+	iPendingNotificationEventList.Close();
+	iCompanyIdList.Close();
+	iOutBuf.Close();
+
+	// Free up all the settings memory
+	THashMapIter<TInt, CPlayerApplicationSettings*> iter(iPlayerApplicationSettings);
+	CPlayerApplicationSettings* const* setting = iter.NextValue();
+	while ( setting != NULL )
+		{
+		delete *setting;
+		setting = iter.NextValue();
+		}
+
+	// Now close the hash table itself
+	iPlayerApplicationSettings.Close();
+	delete iSupportedNotificationEventList;
+	}
+	
+		
+TAny* CPlayerInfoTarget::GetInterfaceIf(TUid aUid)
+	{
+	TAny* ret = NULL;
+	if ( aUid == TUid::Uid(KRemConInterfaceIf2) )
+		{
+		ret = reinterpret_cast<TAny*>(
+			static_cast<MRemConInterfaceIf2*>(this)
+			);
+		}
+
+	return ret;	
+	}
+
+// from MRemConInterfaceIf
+void CPlayerInfoTarget::MrcibNewMessage(TUint aOperationId, const TDesC8& aData, TRemConMessageSubType aMsgSubType)
+	{
+	LOG(_L("CPlayerInfoTarget::MrcibNewMessage"));
+	LOG1(_L("\taOperationId = 0x%02x"), aOperationId);
+	LOG1(_L("\taData.Length = %d"), aData.Length());
+	LOG1(_L("\taMsgSubType = 0x%02x"), aMsgSubType);
+
+	TMetadataTransferPDU currentOp = RAvrcpIPC::GetPDUIdFromIPCOperationId(aOperationId);
+	
+	switch (currentOp)
+		{
+		case EGetCapabilities:
+			{
+			/* process this in playercapabilities */
+			ProcessGetCapabilities( aData );
+			break;
+			}
+		case EListPlayerApplicationSettingAttributes:	
+			{
+			/* respond with Player Application Attributes*/
+			ProcessListPlayerApplicationAttributes( aOperationId );
+			break;
+			}
+		case EGetPlayerApplicationSettingAttributeText:	
+			{
+			/* respond with Player Application Attribute Text*/
+			ProcessGetPlayerApplicationAttributeText( aData, aOperationId );
+			break;
+			}
+		case EListPlayerApplicationSettingValues:
+			{
+			/* respond with Player Application Values*/
+			ProcessListPlayerApplicationValues( aData, aOperationId );
+			break;
+			}
+		case EGetPlayerApplicationSettingValueText:
+			{
+			/* respond with Application Value Text*/
+			ProcessGetPlayerApplicationValueText( aData, aOperationId );
+			break;
+			}
+		case EGetCurrentPlayerApplicationSettingValue:
+			{
+			/* respond with Current Player Application Value*/
+			ProcessGetCurrentPlayerApplicationValue( aData, aOperationId );
+			break;
+			}
+		case ESetPlayerApplicationSettingValue:
+			{
+			/* Set Player Application Value*/
+			ProcessSetPlayerApplicationValue( aData, aOperationId );
+			break;
+			}
+		case EGetPlayStatus:
+			{
+			// process in playerevents
+			ProcessGetPlayStatus();
+			break;
+			}
+		case ERegisterNotification:
+			{
+			// obtain eventId from aOperationId
+			TRegisterNotificationEvent eventId = RAvrcpIPC::GetEventIdFromIPCOperationId(aOperationId);
+			
+			// register for Notifications
+			if (aMsgSubType == ERemConNotifyCommandAwaitingInterim)
+				{
+				ProcessGetStatusAndBeginObserving(aOperationId, eventId, aData);
+				}
+			else if (aMsgSubType == ERemConNotifyCommandAwaitingChanged)
+				{
+				ProcessGetStatus(aOperationId, eventId);
+				}
+		 	break;
+		 	}
+		case EGetPlayStatusUpdate:
+			{
+			// process in playerevents
+			ProcessGetPlayStatusUpdate(aData);
+			break;
+			}
+		default:
+			break;
+		}
+		
+	}
+
+MPlayerEventsObserver::TTargetBatteryStatus CPlayerInfoTarget::DetectBatteryStatus()
+	{
+	MPlayerEventsObserver::TTargetBatteryStatus status = ECritical;
+	TInt err = KErrNone;
+	TInt batteryStatus = EBatteryStatusUnknown;
+	TInt chargingStatus = EChargingStatusNotConnected;
+	err = RProperty::Get(KPSUidHWRMPowerState,KHWRMBatteryStatus,batteryStatus);
+	if (!err)
+		{
+		err = RProperty::Get(KPSUidHWRMPowerState,KHWRMChargingStatus,chargingStatus);
+		}
+
+	switch (batteryStatus)
+		{
+		// Normal or Charging
+		case EBatteryStatusOk:
+			{
+			if (chargingStatus == EChargingStatusCharging ||
+				chargingStatus == EChargingStatusAlmostComplete ||
+				chargingStatus == EChargingStatusChargingContinued)
+				{
+				iBatteryStatus = EExternal;
+				}
+			else
+				{
+				if (chargingStatus == EChargingStatusChargingComplete)
+					{
+					iBatteryStatus = EFullCharge;
+					}
+				else
+					{
+					iBatteryStatus = ENormal;
+					}
+				}
+			}
+			break;
+		// Warning
+		case EBatteryStatusLow:
+			{
+			iBatteryStatus = EWarning;
+			}
+			break;
+		// Critical
+		case EBatteryStatusEmpty:
+			{
+			iBatteryStatus = ECritical;
+			}
+			break;
+		// Unknown state, set as ECritical
+		case EBatteryStatusUnknown:
+			{
+			iBatteryStatus = ECritical;
+			}
+			break;
+		}
+	return status;
+	}