bluetoothappprofiles/avrcp/playerinformation/src/playersettings.cpp
changeset 0 f63038272f30
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetoothappprofiles/avrcp/playerinformation/src/playersettings.cpp	Mon Jan 18 20:28:57 2010 +0200
@@ -0,0 +1,685 @@
+// 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 <remconinterfaceselector.h>
+#include <playerinformationtarget.h>
+
+#include "playerapplicationsetting.h"
+#include "playerinformation.h"
+#include "playersettingsutils.h"
+
+
+void CPlayerInfoTarget::SendError(TInt aError, TInt aOperationId)
+	{
+	TInt error = 0;
+	RAvrcpIPCError response;
+	response.iError = aError;
+	TRAP(error, response.WriteL(iOutBuf));   // Try to send internal error if OOM
+	if (error == KErrNone)
+		{
+		InterfaceSelector().SendUnreliable(TUid::Uid(KRemConPlayerInformationUid),
+										aOperationId, ERemConResponse, iOutBuf);
+		}								
+	}
+
+
+// PDU 0x11
+void CPlayerInfoTarget::ProcessListPlayerApplicationAttributes(TInt aOperationId)
+	{
+	RRemConPlayerListOfAttributes response;
+	response.iNumberAttributes = iPlayerApplicationSettings.Count();
+
+	THashMapIter<TInt, CPlayerApplicationSettings*> iter(iPlayerApplicationSettings);
+	const TInt* attribute = iter.NextKey();
+	while ( attribute != NULL )
+		{
+		if (response.iAttributes.Append(*attribute) != KErrNone)
+			{
+			response.Close();
+			return SendError(KErrAvrcpMetadataInternalError, aOperationId);   // Try to send internal error if OOM
+			}
+		attribute = iter.NextKey();
+		}
+
+	// send the response back to the CT
+	TInt error = 0;
+	TRAP(error, response.WriteL(iOutBuf));   // Try to send internal error if OOM
+	response.Close();
+	if (error != KErrNone)
+		{
+		return SendError(KErrAvrcpMetadataInternalError, aOperationId);
+		}
+		
+	InterfaceSelector().SendUnreliable(TUid::Uid(KRemConPlayerInformationUid),
+									EListPlayerApplicationSettingAttributes, ERemConResponse, iOutBuf );
+	}
+
+// PDU 0x12
+void CPlayerInfoTarget::ProcessListPlayerApplicationValues(const TDesC8& aData, TInt aOperationId)
+	{
+	TInt error =0;
+	RDesReadStream readStream;
+	readStream.Open(aData);
+	TInt attributeID = 0;
+	TRAP(error, attributeID = readStream.ReadUint8L());
+	readStream.Close();
+	if (error != KErrNone)
+		{
+		return SendError(KErrAvrcpMetadataParameterNotFound, aOperationId);  // Nothing in packet
+		}
+		
+	// Send the number of values for this attribute (1 byte),
+	// followed by the defined values themselves (n x 1byte)
+	CPlayerApplicationSettings* thisSetting = GetSetting(attributeID);
+	if (thisSetting == NULL) 
+		{
+		// Attribute Id not found
+		return SendError(KErrAvrcpMetadataInvalidParameter, aOperationId);  
+		}
+		
+	RRemConPlayerListOfAttributes response;
+	RArray<TUint>* values = thisSetting->GetValues();
+	TInt numValues = values->Count();
+	response.iNumberAttributes = numValues;
+
+	// Make sure that we always have at least one result to return
+	// Table 5.18 says that the number of results provided has an
+	// allowed value of 1-255, so we cannot return zero results.
+	if (response.iNumberAttributes == 0)
+		{
+		return SendError(KErrAvrcpMetadataParameterNotFound, aOperationId);  // No attributes matched
+		}
+
+	for ( TInt i = 0; i < numValues; i++ )
+		{
+		TInt value = (*values)[i];
+		if (response.iAttributes.Append(value) != KErrNone)
+			{
+			response.Close();
+			return SendError(KErrAvrcpMetadataInternalError, aOperationId);   // Try to send internal error if OOM
+			}
+		}
+
+	// send the response back to the CT
+	TRAP(error, response.WriteL(iOutBuf));   // Try to send internal error if OOM
+	response.Close();
+	if (error != KErrNone)
+		{
+		return SendError(KErrAvrcpMetadataInternalError, aOperationId);
+		}
+		
+	InterfaceSelector().SendUnreliable(TUid::Uid(KRemConPlayerInformationUid),
+									aOperationId, ERemConResponse, iOutBuf );
+	}
+
+// PDU 0x15
+void CPlayerInfoTarget::ProcessGetPlayerApplicationAttributeText(const TDesC8& aData, TInt aOperationId)
+	{
+	TInt error =0;
+
+	// If we can't parse the request, then return an error
+	RRemConPlayerListOfAttributes request;
+	TRAP(error, request.ReadL(aData));
+	if (error != KErrNone)
+		{
+		request.Close();
+		return SendError(KErrAvrcpMetadataInvalidCommand, aOperationId);
+		}
+		
+	// Iterate through requested attributes and remove
+	// those which we don't have any settings for.
+	for (TInt i = 0; i < request.iNumberAttributes; i++)
+		{
+		if (! AttributeSettingExists(request.iAttributes[i]))
+			{
+			request.iAttributes.Remove(i);
+			request.iNumberAttributes--;
+			i--;
+			}
+		}
+		
+	// Make sure that we always have at least one result to return
+	// Table 5.18 says that the number of results provided has an
+	// allowed value of 1-255, so we cannot return zero results.
+	RRemConGetPlayerApplicationTextResponse response;
+	response.iNumberAttributes = request.iNumberAttributes;
+	if (response.iNumberAttributes == 0)
+		{
+		request.Close();
+		return SendError(KErrAvrcpMetadataInvalidParameter, aOperationId);  // No attributes matched
+		}
+
+	// for every attribute text requested
+	for (TInt i = 0; i < request.iNumberAttributes; i++)
+		{
+		// start with the attribute id requested and the character set
+		RSettingWithCharset setting;
+		TInt attId = request.iAttributes[i];
+		CPlayerApplicationSettings* thisSetting = GetSetting(attId);
+		setting.iAttributeId = attId;
+		setting.iCharset = KUtf8MibEnum;
+		const TPtrC8 text = thisSetting->GetAttributeText();
+		setting.iStringLen = text.Length();
+		setting.iString = text.Alloc();
+		
+		// If OOM, try to return an internal error.
+		if (setting.iString == NULL)
+			{
+			request.Close();
+			response.Close();
+			return SendError(KErrAvrcpMetadataInternalError, aOperationId);
+			}
+			
+		// If OOM, try to return an internal error.
+		if (response.iAttributes.Append(setting) != KErrNone)
+			{
+			setting.Close();
+			request.Close();
+			response.Close();
+			return SendError(KErrAvrcpMetadataInternalError, aOperationId);
+			}
+		}
+	request.Close();
+	
+	// Allocate a buffer for the formatted message
+	RBuf8 messageBuffer;
+	if ( messageBuffer.Create(response.Size()) != KErrNone )
+		{
+		// On OOM drop the message
+		response.Close();
+		return;
+		}
+		
+	// send the response back to the CT
+	TRAP(error, response.WriteL(messageBuffer));   // Try to send internal error if OOM
+	response.Close();
+	if (error != KErrNone)
+		{
+		messageBuffer.Close();
+		return SendError(KErrAvrcpMetadataInternalError, aOperationId);
+		}
+		
+	InterfaceSelector().SendUnreliable(TUid::Uid(KRemConPlayerInformationUid),
+									aOperationId, ERemConResponse, messageBuffer );
+	
+	messageBuffer.Close();
+	}
+
+// PDU 0x14
+void CPlayerInfoTarget::ProcessSetPlayerApplicationValue(const TDesC8& aData, TInt aOperationId)
+	{
+	RRemConPlayerAttributeIdsAndValues request;
+	TInt error = 0;
+
+	// If we can't parse the request, then return an error
+	TRAP(error, request.ReadL(aData));
+	if (error != KErrNone)
+		{
+		request.Close();
+		return SendError(KErrAvrcpMetadataInvalidCommand, aOperationId);
+		}
+		
+	// Iterate through all the settings we're sent to update and set them
+	for (TInt i = 0; i < request.iNumberAttributes; i++)
+		{
+		if (! AttributeValueCanBeSet(request.iAttributeId[i], request.iAttributeValue[i]))
+			{
+			// remove this setting
+			request.iAttributeId.Remove(i);
+			request.iAttributeValue.Remove(i);
+			request.iNumberAttributes--;
+			i--;
+			}
+		}
+	__ASSERT_DEBUG(request.iAttributeId.Count() == request.iAttributeValue.Count(), PlayerSettingsUtils::Panic(EPlayerSettingsFunnyLengthData));
+	
+	// Section 5.7 of the AVRCP specification (page 56) says:
+	// If CT sent a PDU with nonexistent PDU ID or a PDU containing
+	// only one parameter with nonexistent parameter ID, TG shall return
+	// REJECTED response with Error Status Code. If CT sent a PDU with
+	// multiple parameters where at least one ID is existent and the
+	// others are nonexistent, TG shall proceed with the existent ID and
+	// ignore the non-existent IDs.
+	//
+	// This means we return REJECTED if we have nothing to set
+	if (request.iNumberAttributes == 0)
+		{
+		request.Close();
+		return SendError(KErrAvrcpMetadataInvalidParameter, aOperationId);
+		}
+		
+	// If an application setting notifier has been requested then notify it
+	// If the notification succeeds, then set all the values
+
+	TRAP(error, iApplicationSettingNotifier.MpasnSetPlayerApplicationValueL(request.iAttributeId, request.iAttributeValue));
+	if ( error == KErrNone )
+		{
+		for (TInt i = 0; i < request.iNumberAttributes; i++)
+			{
+			CPlayerApplicationSettings* thisSetting = GetSetting(request.iAttributeId[i]);
+			thisSetting->SetCurrentValue(request.iAttributeValue[i]);
+			}
+		}
+	else
+		{
+		// Return an AVRCP internal error via RemCon. See section 5.7.1 of specification.
+		request.Close();
+		return SendError(KErrAvrcpMetadataInternalError, aOperationId);
+		}
+		
+	request.Close();
+     // Send a notification if one has been registered
+     if ( KErrNotFound != iPendingNotificationEventList.Find( ERegisterNotificationPlayerApplicationSettingChanged ))
+          {
+           SendNotificationResponse( ERegisterNotificationPlayerApplicationSettingChanged, ERemConNotifyResponseChanged );
+          }
+       
+		
+	// SendError KErrNone is used to send a valid response
+	SendError(KErrNone, aOperationId);
+	}
+
+// PDU 0x13
+void CPlayerInfoTarget::ProcessGetCurrentPlayerApplicationValue(const TDesC8& aData, TInt aOperationId)
+	{
+	TInt error = 0;
+
+	// If we can't parse the request, then return an error
+	RRemConPlayerListOfAttributes request;
+	TRAP(error, request.ReadL(aData));
+	if (error != KErrNone)
+		{
+		request.Close();
+		return SendError(KErrAvrcpMetadataInvalidCommand, aOperationId);
+		}
+		
+	// Look through requested attributes, and assemble a response
+	// for those which we posess. If none are found, return an error
+	RRemConPlayerAttributeIdsAndValues response;
+	response.iNumberAttributes = 0;
+	request.iAttributes.Sort();
+	
+	for (TInt i = 0; i < request.iNumberAttributes; i++)
+		{
+		TInt attToSend = request.iAttributes[i];
+		if (AttributeSettingExists(attToSend))
+			{
+			TInt ret1 = response.iAttributeId.Append(attToSend);
+			TInt ret2 = response.iAttributeValue.Append(GetSetting(attToSend)->GetCurrentValue());
+			if (ret1 != KErrNone || ret2 != KErrNone)
+				{
+				request.Close();
+				response.Close();
+				return SendError(KErrAvrcpMetadataInternalError, aOperationId);   // Try to send internal error if OOM
+				}
+			response.iNumberAttributes++;
+			}
+		}
+	request.Close();
+		
+	// Make sure that we always have at least one result to return
+	// Table 5.18 says that the number of results provided has an
+	// allowed value of 1-255, so we cannot return zero results.
+	if (response.iNumberAttributes == 0)
+		{
+		response.Close();
+		return SendError(KErrAvrcpMetadataInvalidParameter, aOperationId);  // No attributes matched
+		}
+		
+	// send the response back to the CT
+	TRAP(error, response.WriteL(iOutBuf));   // Try to send internal error if OOM
+	response.Close();
+	if (error != KErrNone)
+		{
+		return SendError(KErrAvrcpMetadataInternalError, aOperationId);
+		}
+		
+	InterfaceSelector().SendUnreliable(TUid::Uid(KRemConPlayerInformationUid),
+									aOperationId, ERemConResponse, iOutBuf );
+	}
+
+// PDU 0x16
+void CPlayerInfoTarget::ProcessGetPlayerApplicationValueText(const TDesC8& aData, TInt aOperationId)
+	{
+	RDesReadStream readStream;
+	readStream.Open(aData);
+
+	TInt error = 0;
+	TInt reqAttribute = 0;
+	
+	// Read the attribute id
+	TRAP(error, reqAttribute = readStream.ReadUint8L());
+	if (error != KErrNone)
+		{
+		readStream.Close();
+		return SendError(KErrAvrcpMetadataParameterNotFound, aOperationId);  // Nothing in packet
+		}
+		
+	// If we don't have settings for this attribute, return an error
+	CPlayerApplicationSettings* thisSetting = GetSetting(reqAttribute);
+	if (thisSetting == NULL)
+		{
+		readStream.Close();
+		return SendError(KErrAvrcpMetadataInvalidParameter, aOperationId);  // Attribute not found
+		}
+		
+	// Read the number of PAS values
+	TInt numSettings = 0;
+	TRAP(error, numSettings = readStream.ReadUint8L());
+	if (error != KErrNone)
+		{
+		readStream.Close();
+		return SendError(KErrAvrcpMetadataParameterNotFound, aOperationId);  // Nothing in packet
+		}
+	
+	RArray<TInt> valueTextsRequested;
+	for (TInt i = 0; i < numSettings; i++)
+		{
+		TInt requestedValueText = 0;
+		TRAP(error, requestedValueText = readStream.ReadUint8L());
+		if (error == KErrNone)
+			{
+			if (valueTextsRequested.Append(requestedValueText) != KErrNone)
+				{
+				readStream.Close();
+				return SendError(KErrAvrcpMetadataInternalError, aOperationId);   // Try to send internal error if OOM
+				}
+			}
+		}
+	
+	readStream.Close();
+	
+	// format the response in a RRemConGetPlayerApplicationTextResponse
+	RRemConGetPlayerApplicationTextResponse response;
+	response.iNumberAttributes = 0;
+
+	// for every attribute text requested
+	RPointerArray<HBufC8>* textValues = thisSetting->GetValuesTexts();
+	RArray<TUint>* values = thisSetting->GetValues();
+	TInt numRequested = valueTextsRequested.Count();
+	for (TInt i = 0; i < numRequested; i++)
+		{
+		// start with the attribute id requested and the character set
+		RSettingWithCharset setting;
+		TInt valueToSend = valueTextsRequested[i];
+		setting.iAttributeId = valueToSend;
+		setting.iCharset = KUtf8MibEnum;
+
+		// text length followed by the text
+		TInt found = values->Find(valueToSend);
+		if (found != KErrNotFound)
+			{
+			HBufC8* text = (*textValues)[found];
+			setting.iStringLen = text->Length();
+			setting.iString = text->Alloc();
+			
+			// If OOM, try to return an internal error.
+			if (setting.iString == NULL)
+				{
+				response.Close();
+				valueTextsRequested.Close();
+				return SendError(KErrAvrcpMetadataInternalError, aOperationId);
+				}
+				
+			// If OOM, try to return an internal error. Of course, this could fail too
+			if (response.iAttributes.Append(setting) != KErrNone)
+				{
+				response.Close();
+				setting.Close();
+				valueTextsRequested.Close();
+				return SendError(KErrAvrcpMetadataInternalError, aOperationId);
+				}
+				
+			response.iNumberAttributes++;
+			}
+		}
+	valueTextsRequested.Close();
+	
+	// Make sure that we always have at least one result to return
+	// Table 5.18 says that the number of results provided has an
+	// allowed value of 1-255, so we cannot return zero results.
+	if (response.iNumberAttributes == 0)
+		{
+		response.Close();
+		return SendError(KErrAvrcpMetadataInvalidParameter, aOperationId);
+		}
+		
+	// Allocate a buffer for the formatted message
+	RBuf8 messageBuffer;
+	if ( messageBuffer.Create(response.Size()) != KErrNone )
+		{
+		// On OOM drop the message
+		response.Close();
+		return;
+		}
+		
+	// send the response back to the CT
+	TRAP(error, response.WriteL(messageBuffer));   // Try to send internal error if OOM
+	response.Close();
+	if (error != KErrNone)
+		{
+		messageBuffer.Close();
+		return SendError(KErrAvrcpMetadataInternalError, aOperationId);
+		}
+		
+	InterfaceSelector().SendUnreliable(TUid::Uid(KRemConPlayerInformationUid),
+									aOperationId, ERemConResponse, messageBuffer );
+	messageBuffer.Close();
+	}
+
+TBool CPlayerInfoTarget::AttributeSettingExists(TUint anAttributeID)
+	{
+	if (GetSetting(anAttributeID) == NULL)
+		{
+		return EFalse;
+		}
+	else
+		{
+		return ETrue;
+		}
+	}
+
+TBool CPlayerInfoTarget::IsValidAttributeValue(TUint anAttributeID, TUint anAttributeValue)
+	{
+	// As defined in Appendix F of the AVRCP specification, page 81
+	// Attribute 0x01 - range 0x01 to 0x02
+	// Attribute 0x02 - range 0x01 to 0x04
+	// Attribute 0x03 - range 0x01 to 0x03
+	// Attribute 0x04 - range 0x01 to 0x03
+	// Attribute 0x05 - 0x7f -- invalid; reserved for future use
+	// Attribute 0x80 - 0xff -- vendor dependent
+	if (anAttributeID >= 0x80 && anAttributeID <= 0xff && anAttributeValue <= 0xff )
+		{
+		return ETrue;
+		}
+		
+	if (anAttributeID == 0x01 && anAttributeValue >= 0x01 && anAttributeValue <= 0x02)
+		{
+		return ETrue;
+		}
+		
+	if (anAttributeID == 0x02 && anAttributeValue >= 0x01 && anAttributeValue <= 0x04)
+		{
+		return ETrue;
+		}
+		
+	if ((anAttributeID == 0x03 || anAttributeID == 0x04)
+		&& anAttributeValue >= 0x01 && anAttributeValue <= 0x03)
+		{
+		return ETrue;
+		}
+		
+	// Everything else is invalid, as defined by the specification
+	return EFalse;
+	}
+
+// Check that anAttributeValue is in the valid value list for anAttributeID
+TBool CPlayerInfoTarget::AttributeValueCanBeSet(TUint anAttributeID, TUint anAttributeValue)
+	{
+	CPlayerApplicationSettings* thisSetting = GetSetting(anAttributeID);
+	if (thisSetting == NULL)
+		{
+		return EFalse;
+		}
+		
+	RArray<TUint>* values = thisSetting->GetValues();
+	if (values == NULL)
+		{
+		return EFalse;
+		}
+		
+	if (values->Find(anAttributeValue) == KErrNotFound)
+		{
+		return EFalse;
+		}
+		
+	// This attribute id and value has been already defined by the RSS
+	// file, and checked that it conforms to the specification when the
+	// RSS file was loaded. Now allow this value to be set over the air.
+	return ETrue;
+	}
+
+CPlayerApplicationSettings* CPlayerInfoTarget::GetSetting(TUint anAttributeID)
+	{
+	// Will return NULL if anAttributeID is not found
+	CPlayerApplicationSettings** settings = iPlayerApplicationSettings.Find(anAttributeID);
+	if (settings == NULL)
+		{
+		return NULL;
+		}
+		
+	return *settings;
+	}
+
+
+// from MPlayerApplicationSettingsObserver
+// exported function wrapper for internal pure virtual
+EXPORT_C void MPlayerApplicationSettingsObserver::DefineAttributeL(TUint aAttributeID,
+																	TDesC8& aAttributeText,
+																	RArray<TUint>& aValues,
+																	RArray<TPtrC8>& aValueTexts,
+																	TUint aInitialValue)
+	{
+	DoDefineAttributeL(aAttributeID, aAttributeText, aValues, aValueTexts, aInitialValue);
+	}
+
+EXPORT_C void MPlayerApplicationSettingsObserver::SetAttributeL(TUint aAttributeID, TUint aValue)
+	{
+	DoSetAttributeL(aAttributeID, aValue );
+	}
+
+void CPlayerInfoTarget::DoDefineAttributeL(TUint aAttributeID,
+											TDesC8& aAttributeText,
+											RArray<TUint>& aValues,
+											RArray<TPtrC8>& aValueTexts,
+											TUint aInitialValue)
+	{
+	//Check Length of the player application setting attribute string is 1-255
+	if(aAttributeText.Length() > KMaxPlayerApplicationSettingsValue || 
+			aAttributeText.Length() < KMinPlayerApplicationSettingsValue )
+		{
+		User::Leave(KErrNotSupported);
+		}
+	
+	//Check the number of player application setting values is 1-255
+	if(aValues.Count() > KMaxPlayerApplicationSettingsValue || 
+			aValues.Count() < KMinPlayerApplicationSettingsValue )
+		{
+		User::Leave(KErrNotSupported);
+		}	
+	
+	//Check the numbers of player application setting values and 
+	//player application setting value texts are equal
+	if(aValues.Count() != aValueTexts.Count())
+		{
+		User::Leave(KErrNotSupported);
+		}
+	
+	//Check Length of the player application setting value string is 1-255
+	for(TInt i = 0; i < aValueTexts.Count(); i++ )
+		{
+		if(aValueTexts[i].Length() > KMaxPlayerApplicationSettingsValue ||
+				aValueTexts[i].Length() < KMinPlayerApplicationSettingsValue )
+			{
+			User::Leave (KErrNotSupported);
+			}			
+		}
+
+	for (TInt i = 0; i < aValues.Count(); i++)
+		{
+		// The user cannot define certain attribute ids or values; see Appendix F
+		if ( ! IsValidAttributeValue(aAttributeID, aValues[i]))
+			{
+			User::Leave(KErrNotSupported);
+			}
+		}
+	
+	// Check the initial value, too
+	if ( ! IsValidAttributeValue(aAttributeID, aInitialValue))
+		{
+		User::Leave(KErrNotSupported);
+		}
+		
+	// check that aInitialValue is in aValues
+	if (aValues.Find(aInitialValue) == KErrNotFound)
+		{
+		User::Leave(KErrNotSupported);
+		}
+		
+	// create a new TPlayerApplicationSettings
+	CPlayerApplicationSettings* newSetting = CPlayerApplicationSettings::NewL(aAttributeID, aAttributeText, aValues, aValueTexts, aInitialValue);
+	CleanupStack::PushL(newSetting);
+	
+	// Backup the settings of aAttributeID if they exist, return NULL if the attribute ID cannot be found
+	CPlayerApplicationSettings* backupSetting = GetSetting(aAttributeID); 
+	
+	// and save it 
+	iPlayerApplicationSettings.InsertL(aAttributeID, newSetting);
+	
+	//Delete backupSetting, as the InsertL will replace the old objects by the provided objects 
+	delete backupSetting;
+	
+	CleanupStack::Pop(newSetting);
+	}
+
+void CPlayerInfoTarget::DoSetAttributeL(TUint aAttributeID, TUint aValue)
+	{
+	// Will return NULL if the attribute ID cannot be found
+	CPlayerApplicationSettings* setting = GetSetting(aAttributeID);
+	if (setting == NULL)
+		{
+		User::Leave(KErrNotFound);
+		}
+		
+	if ( ! IsValidAttributeValue(aAttributeID, aValue))
+		{
+		User::Leave(KErrNotSupported);
+		}
+		
+	setting->SetCurrentValue(aValue);
+	
+	if ( KErrNotFound != iPendingNotificationEventList.Find( ERegisterNotificationPlayerApplicationSettingChanged ))
+		{
+		// send response
+		SendNotificationResponse( ERegisterNotificationPlayerApplicationSettingChanged, ERemConNotifyResponseChanged );
+		}
+	}
+