diff -r 16e4b9007960 -r f5508c13dfe0 bluetoothappprofiles/avrcp/playerinformation/src/playersettings.cpp --- a/bluetoothappprofiles/avrcp/playerinformation/src/playersettings.cpp Wed Oct 13 13:15:31 2010 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,685 +0,0 @@ -// 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 -#include - -#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 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* 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 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* textValues = thisSetting->GetValuesTexts(); - RArray* 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* 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& aValues, - RArray& 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& aValues, - RArray& 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 ); - } - } -