bluetoothappprofiles/avrcp/mediabrowseapi/src/remconmediabrowsetargetbase.cpp
changeset 0 f63038272f30
child 1 6a1fe72036e3
equal deleted inserted replaced
-1:000000000000 0:f63038272f30
       
     1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 
       
    17 
       
    18 /**
       
    19  @file
       
    20  @internalComponent
       
    21  @released
       
    22 */
       
    23 
       
    24 #include <remcon/remconmediabrowsetargetbase.h>
       
    25 #include <remconmediainformationtargetobserver.h>
       
    26 #include <remconinterfaceselector.h>
       
    27 #include <remconmediabrowsepanic.h>
       
    28 #include <bluetooth/logger.h>
       
    29 #include "mediabrowse.h"
       
    30 #include "remconmediabrowsefault.h"
       
    31 #include "remconqueuemessage.h"
       
    32 
       
    33 const TInt KDatabaseUnawareUidCounter = 0;
       
    34 #ifdef __FLOG_ACTIVE
       
    35 _LIT8(KLogComponent, LOG_COMPONENT_REMCONMEDIABROWSEAPI);
       
    36 _LIT8(KLogFormat, "Operation Id = 0x%x, Data Lengh = %d");
       
    37 #endif
       
    38 //=========================================================================================
       
    39 // Construction/Destruction
       
    40 //=========================================================================================
       
    41 CRemConMediaBrowseTargetBase::CRemConMediaBrowseTargetBase(CRemConInterfaceSelector& aInterfaceSelector, 
       
    42 		MRemConDatabaseAwareMediaLibraryBrowseObserver& aMlObserver, 
       
    43 		MRemConDatabaseAwareNowPlayingBrowseObserver& aNpObserver,
       
    44 		TUint16 aMediaLibraryStateCookie)
       
    45 	: CRemConInterfaceBase(TUid::Uid(KRemConMediaBrowseApiUid),
       
    46 			KMaxLengthMediaBrowseMsg,
       
    47 			aInterfaceSelector,
       
    48 			ERemConClientTypeTarget),
       
    49 	iInterfaceSelector(aInterfaceSelector),
       
    50 	iRcdamlbo(&aMlObserver),
       
    51 	iRcdanpbo(&aNpObserver),
       
    52 	iMediaLibraryStateCookie(aMediaLibraryStateCookie),
       
    53 	iAttributeIterator(iMediaAttributeIds),
       
    54 	iNullIterator(iNullArray),
       
    55 	iSearchInProgress(EFalse),
       
    56 	iLastMlscUpdate(aMediaLibraryStateCookie)
       
    57 	{
       
    58 	}
       
    59 
       
    60 CRemConMediaBrowseTargetBase::CRemConMediaBrowseTargetBase(CRemConInterfaceSelector& aInterfaceSelector, 
       
    61 		MRemConDatabaseUnawareMediaLibraryBrowseObserver& aMlObserver, 
       
    62 		MRemConDatabaseUnawareNowPlayingBrowseObserver& aNpObserver)
       
    63 	: CRemConInterfaceBase(TUid::Uid(KRemConMediaBrowseApiUid),
       
    64 			KMaxLengthMediaBrowseMsg,
       
    65 			aInterfaceSelector,
       
    66 			ERemConClientTypeTarget),
       
    67 	iInterfaceSelector(aInterfaceSelector),
       
    68 	iRcdumlbo(&aMlObserver),
       
    69 	iRcdunpbo(&aNpObserver),
       
    70 	iAttributeIterator(iMediaAttributeIds),
       
    71 	iNullIterator(iNullArray),
       
    72 	iSearchInProgress(EFalse)
       
    73 	{
       
    74 	}
       
    75 
       
    76 CRemConMediaBrowseTargetBase::~CRemConMediaBrowseTargetBase()
       
    77 	{
       
    78 	iMediaAttributeIds.Close();
       
    79 	iNullArray.Close();
       
    80 	iOutBuf.Close();
       
    81 	iSearchString.Close();
       
    82 	iGetPathResponse->Close();
       
    83 	iGiaResponse->Close();
       
    84 	iGflResponse->Close();
       
    85 	delete iGetPathResponse;
       
    86 	delete iGiaResponse;
       
    87 	delete iGflResponse;
       
    88 	
       
    89 	if (iNextMessageCallBack)
       
    90 		{
       
    91 		iNextMessageCallBack->Cancel();
       
    92 		delete iNextMessageCallBack;
       
    93 		}
       
    94 	if (iNextItemCallBack)
       
    95 		{
       
    96 		iNextItemCallBack->Cancel();
       
    97 		delete iNextItemCallBack;
       
    98 		}
       
    99 	
       
   100 	iMsgQueue->Reset();
       
   101 	delete iMsgQueue;
       
   102 	}
       
   103 
       
   104 void CRemConMediaBrowseTargetBase::BaseConstructL(TBool aSearchSupported)
       
   105 	{
       
   106 	iMsgQueue = new(ELeave)TRemConMessageQueue();
       
   107 
       
   108 	iGetPathResponse = new(ELeave)RRemConGetPathResponse();
       
   109 	iGiaResponse = new(ELeave)RRemConGetItemAttributesResponse();
       
   110 	iGflResponse = new(ELeave)RRemConGetFolderItemsResponse();
       
   111 
       
   112 	TCallBack cb(&NextMessageCb, this);
       
   113 	iNextMessageCallBack = new(ELeave)CAsyncCallBack(cb, CActive::EPriorityStandard);
       
   114 	
       
   115 	TCallBack itemCallBack(&NextItemCallBack, this);
       
   116 	iNextItemCallBack = new(ELeave)CAsyncCallBack(itemCallBack, CActive::EPriorityStandard);
       
   117 	
       
   118 	RRemConInterfaceFeatures features;
       
   119 	User::LeaveIfError(features.Open());
       
   120 	CleanupClosePushL(features);
       
   121 
       
   122 	if(aSearchSupported)
       
   123 		{
       
   124 		features.AddOperationL(ESearchOperationId);
       
   125 		iSearchSupported = ETrue;
       
   126 		}
       
   127 	
       
   128 	if(DatabaseAware())
       
   129 		{
       
   130 		features.AddOperationL(EUIDPersistency);
       
   131 		}
       
   132 	
       
   133 	//Mandate the following operationIds to be supported in the client
       
   134 	features.AddOperationL(EGetFolderItemsOperationId);
       
   135 	features.AddOperationL(EChangePathOperationId);
       
   136 	features.AddOperationL(EGetItemAttributesOperationId);
       
   137 	features.AddOperationL(ESetBrowsedPlayerOperationId);
       
   138 	
       
   139 	iOutBuf.CreateL(KMediaBrowseOutBufMaxLength);
       
   140 	
       
   141 	CRemConInterfaceBase::BaseConstructL(features, ETrue); // it's true, this interface is a bulk interface
       
   142 	CleanupStack::PopAndDestroy(&features);
       
   143 	}
       
   144 	
       
   145 //=========================================================================================
       
   146 // RemCon interface stuff, called from interface selector
       
   147 //=========================================================================================
       
   148 
       
   149 /** 
       
   150 @internalComponent
       
   151 @released
       
   152 
       
   153 Gets a pointer to a specific interface version.
       
   154 
       
   155 @return A pointer to the interface, NULL if not supported.
       
   156 */
       
   157 TAny* CRemConMediaBrowseTargetBase::GetInterfaceIf(TUid aUid)
       
   158 	{
       
   159 	TAny* ret = NULL;
       
   160 	if ( aUid == TUid::Uid(KRemConInterfaceIf1) )
       
   161 		{
       
   162 		ret = reinterpret_cast<TAny*>(
       
   163 			static_cast<MRemConInterfaceIf*>(this)
       
   164 			);
       
   165 		}
       
   166 
       
   167 	return ret;
       
   168 	}
       
   169 
       
   170 void CRemConMediaBrowseTargetBase::MrcibNewMessage(TUint aOperationId,
       
   171 			const TDesC8& aData)
       
   172 	{
       
   173 	LOG_FUNC
       
   174 	LOG2(KLogFormat, aOperationId, aData.Length());
       
   175 
       
   176 	TMetadataTransferPDU currentOp = RAvrcpIPC::GetPDUIdFromIPCOperationId(aOperationId);
       
   177 	switch(currentOp)
       
   178 		{
       
   179 	case EGetFolderItemsOperationId:
       
   180 		AddToOperationQueue(EMbGetFolderItems, 
       
   181 							EGetFolderItemsOperationId, aData);
       
   182 		if (!iMsgQueue->IsEmpty() && !iInProgress && !iMsgQueue->Find(
       
   183 			      TUid::Uid(KRemConMediaBrowseApiUid)
       
   184 				 ,EGetFolderItemsOperationId))
       
   185 			{
       
   186 			iNextMessageCallBack->CallBack();
       
   187 			}
       
   188 		break;
       
   189 	case EChangePathOperationId:
       
   190 		ProcessChangePath(aData);
       
   191 		break;
       
   192 	case EGetItemAttributesOperationId:
       
   193 		{
       
   194 		AddToOperationQueue(EMbGetItemAttributes, 
       
   195 							EGetItemAttributesOperationId, aData);
       
   196 		if (!iMsgQueue->IsEmpty() && !iInProgress && !iMsgQueue->Find(
       
   197 					      TUid::Uid(KRemConMediaBrowseApiUid)
       
   198 						 ,EGetItemAttributesOperationId))
       
   199 					{
       
   200 					iNextMessageCallBack->CallBack();
       
   201 					}
       
   202 		break;
       
   203 		}
       
   204 	case ESearchOperationId:
       
   205 		ProcessSearch(aData);
       
   206 		break;
       
   207 	case ESetBrowsedPlayerOperationId:
       
   208 		ProcessGetPath(aData);
       
   209 		break;	
       
   210 	case EMediaLibraryStateCookieUpdateOperationId:
       
   211 		ProcessMediaLibraryStateCookieUpdate(aData);
       
   212 		break;
       
   213 	default:
       
   214 		__ASSERT_DEBUG(EFalse, MediaBrowseFault::Fault(EUnexpectedOperationId));
       
   215 		break; 
       
   216 		};
       
   217 	}
       
   218 
       
   219 //=========================================================================================
       
   220 // Browse Interface functions, called from derived classes
       
   221 //=========================================================================================
       
   222 void CRemConMediaBrowseTargetBase::DoFolderListing(const TArray<TRemConItem>& aFolderListing, 
       
   223 		TUint16 aMediaLibraryStateCookie, 
       
   224 		TInt aResult)
       
   225 	{
       
   226 	if (aResult != KErrNone)
       
   227 		{
       
   228 		SendGetFolderItemsResponse(aResult, KNullDesC8);
       
   229 		return;
       
   230 		}	
       
   231 	
       
   232 	// If asserted here, means the client calls the interface FolderListing() 
       
   233 	// more than once corresponding to the only once call 
       
   234 	// MrcmbtoGetFolderListing()
       
   235 	__ASSERT_DEBUG(iGflResponse->iItems.Count() == 0, MediaBrowsePanic::Panic(EFolderListingProvidedTwice));
       
   236 	
       
   237 	// Store clients state cookie to pass it back when requesting each item. 
       
   238 	// This will ensure that we don't miss state change during the course of 
       
   239 	// the non-atomic GetFolderListing operation
       
   240 	iGflResponse->iUidCounter = aMediaLibraryStateCookie;
       
   241 	
       
   242 	// Store these UIDs, then ask for info about them
       
   243 	if (iGflResponse->CopyItems(aFolderListing) != KErrNone)
       
   244 		{
       
   245 		SendGetFolderItemsResponse(KErrAvrcpAirInternalError, KNullDesC8);
       
   246 		return;
       
   247 		}
       
   248 	
       
   249 	iGflResponse->iCurrentListingSize = KGetFolderItemsResponseBaseSize;
       
   250 	iGflResponse->iCurrentItem = -1;
       
   251 	RequestNextItem();
       
   252 	}
       
   253 
       
   254 void CRemConMediaBrowseTargetBase::DoFolderUpResult(TUint aItemCount, TInt aResult)
       
   255 	{
       
   256 	SendChangePathResponse(aItemCount, aResult);
       
   257 	}
       
   258 
       
   259 void CRemConMediaBrowseTargetBase::DoFolderDownResult(TUint aItemCount, TInt aResult)
       
   260 	{
       
   261 	SendChangePathResponse(aItemCount, aResult);
       
   262 	}
       
   263 
       
   264 void CRemConMediaBrowseTargetBase::DoGetPathResult(TUint aItemCount, 
       
   265 		TUint16 aMediaLibraryStateCookie, 
       
   266 		TInt aResult)
       
   267 	{
       
   268 	if (aResult != KErrNone)
       
   269 		{
       
   270 		iGetPathResponse->Close();
       
   271 		return SendError(EMbSetBrowsedPlayer,
       
   272 				ESetBrowsedPlayerOperationId, aResult);
       
   273 		}
       
   274 	
       
   275 	// Store the current UIDs counter.
       
   276 	iMediaLibraryStateCookie = aMediaLibraryStateCookie;
       
   277 	
       
   278 	TInt status = KErrAvrcpAirBase - KErrAvrcpAirSuccess;
       
   279 	iGetPathResponse->iStatus = status;
       
   280 	iGetPathResponse->iUidCounter = aMediaLibraryStateCookie;
       
   281 	iGetPathResponse->iNumberItems = aItemCount;
       
   282 	
       
   283 	RBuf8 responseBuf;
       
   284 	TInt error = responseBuf.Create(iGetPathResponse->Size());
       
   285 	if (error != KErrNone)
       
   286 		{
       
   287 		iGetPathResponse->Close();
       
   288 		return SendError(EMbSetBrowsedPlayer, 
       
   289 				ESetBrowsedPlayerOperationId, KErrAvrcpAirInternalError);
       
   290 		}
       
   291 	
       
   292 	iGetPathResponse->iPduId = AvrcpBrowsing::ESetBrowsedPlayer;
       
   293 	TRAP(error, iGetPathResponse->WriteL(responseBuf));
       
   294 	if (error == KErrNone)
       
   295 		{
       
   296 		// Send the response back to the CT
       
   297 		error = InterfaceSelector().SendBulkUnreliable(
       
   298 				TUid::Uid(KRemConMediaBrowseApiUid),
       
   299 				ESetBrowsedPlayerOperationId, responseBuf );
       
   300 		}
       
   301 	
       
   302 	iGetPathResponse->Close();
       
   303 	responseBuf.Close();
       
   304 	}
       
   305 
       
   306 void CRemConMediaBrowseTargetBase::DoSearchResult(TUint aNumberItemsFound,
       
   307 		TUint16 aMediaLibraryStateCookie, 
       
   308 		TInt aResult)
       
   309 	{
       
   310 	// GetFoldItems should in progress When this interface is called.
       
   311 	__ASSERT_DEBUG(iSearchInProgress, MediaBrowsePanic::Panic(ESearchResultWithoutRequest));
       
   312 
       
   313 	SendSearchResponse(aResult, aNumberItemsFound, aMediaLibraryStateCookie);
       
   314 	}
       
   315 
       
   316 void CRemConMediaBrowseTargetBase::DoMediaLibraryStateChange(TUint16 aMediaLibraryStateCookie)
       
   317 	{
       
   318 	if(DatabaseAware())
       
   319 		{
       
   320 		__ASSERT_DEBUG(aMediaLibraryStateCookie != KDatabaseUnawareUidCounter, MediaBrowsePanic::Panic(EZeroMediaLibraryStateCookie));
       
   321 		
       
   322 		// For database aware players we need to update if we have a pending update and
       
   323 		// the new value is different to what we last 
       
   324 		if(iMlscUpdatePending && (aMediaLibraryStateCookie != iLastMlscUpdate))
       
   325 			{
       
   326 			// Send update with new value
       
   327 			SendMediaLibraryStateCookieUpdateResponse(aMediaLibraryStateCookie);
       
   328 			}	
       
   329 		
       
   330 		// Always store the last value here.  When we are asked for an update
       
   331 		// we will be provided with the value the update should be relative 
       
   332 		// to, so we will compare to this. 
       
   333 		iLastMlscUpdate = aMediaLibraryStateCookie;
       
   334 		}
       
   335 	else
       
   336 		{
       
   337 		__ASSERT_DEBUG(aMediaLibraryStateCookie == KDatabaseUnawareUidCounter, MediaBrowseFault::Fault(ENonZeroMediaLibraryStateCookie));
       
   338 		
       
   339 		if(iMlscUpdatePending)
       
   340 			{
       
   341 			SendMediaLibraryStateCookieUpdateResponse(aMediaLibraryStateCookie);
       
   342 			}
       
   343 		else
       
   344 			{
       
   345 			// For database aware clients the value can never change.  Indicate that
       
   346 			// the client has informed us of the state change by incrementing our
       
   347 			// update value so that we know there's been a change.  The value doesn't
       
   348 			// matter, we just have to make it something other than zero.
       
   349 			iLastMlscUpdate = 1;
       
   350 			}
       
   351 		}
       
   352 	}
       
   353 
       
   354 void CRemConMediaBrowseTargetBase::DoFolderItemResult(const TRemConItemUid& aFolderID,
       
   355 		const TDesC8& aFolderName, 
       
   356 		TFolderItemType aFolderType, 
       
   357 		TFolderItemPlayable aPlayable,
       
   358 		const TArray<TMediaElementAttribute>& aAttributes,
       
   359 		TInt aResult)
       
   360 	{
       
   361 	// GetFolderItems should in progress When this interface is called.
       
   362 	__ASSERT_DEBUG(iGetFolderListing || iGetItemAttributes, MediaBrowsePanic::Panic(EFolderItemResultWithoutRequest));
       
   363 
       
   364 	if(iGetFolderListing)
       
   365 		{
       
   366 		ProcessFolderItemResult(aFolderID, aFolderName, aFolderType, aPlayable, aResult);
       
   367 		}
       
   368 	
       
   369 	if (iGetItemAttributes)
       
   370 		{
       
   371 		ProcessGetItemAttributesResult(aAttributes, aResult);
       
   372 		}
       
   373 	}
       
   374 
       
   375 void CRemConMediaBrowseTargetBase::DoMediaElementItemResult(const TRemConItemUid& aMediaID, 
       
   376 		const TDesC8& aMediaName, 
       
   377 		TMediaItemType aMediaType, 
       
   378 		const TArray<TMediaElementAttribute>& aAttributes,
       
   379 		TInt aResult)
       
   380 	{
       
   381 	__ASSERT_DEBUG((iGetFolderListing || iGetItemAttributes), MediaBrowsePanic::Panic(EMediaElementItemResultWithoutRequest));
       
   382 
       
   383 	if (iGetFolderListing)
       
   384 		{
       
   385 		ProcessMediaElementItemResult(aMediaID, aMediaName, aMediaType, aAttributes, aResult);
       
   386 		}
       
   387 	
       
   388 	if (iGetItemAttributes)
       
   389 		{
       
   390 		ProcessGetItemAttributesResult(aAttributes, aResult);
       
   391 		}		
       
   392 	}
       
   393 
       
   394 //=========================================================================================
       
   395 // Utility functions, called internally
       
   396 //=========================================================================================
       
   397 
       
   398 void CRemConMediaBrowseTargetBase::ProcessMediaLibraryStateCookieUpdate(const TDesC8& aData)
       
   399 	{
       
   400 	// Try to read the incoming request
       
   401 	RRemConUidsChangedRequest request;
       
   402 	TRAPD(error, request.ReadL(aData));
       
   403 	__ASSERT_DEBUG(error == KErrNone, MediaBrowseFault::Fault(EBadlyFormattedMediaLibraryStateCookieUpdate));
       
   404 	static_cast<void>(error == error); // stops compiler warnings (assert above indicates design contract).
       
   405 
       
   406 	if(request.iInitialUidCounter != iLastMlscUpdate)
       
   407 		{
       
   408 		// The client has updated the uid counter since the bearer
       
   409 		// last asked.  Tell it the new value.  The Send..Response 
       
   410 		// function deals with all the state management necessary,
       
   411 		// including whether we are database aware or unaware
       
   412 		SendMediaLibraryStateCookieUpdateResponse(iLastMlscUpdate);
       
   413 		}
       
   414 	else
       
   415 		{
       
   416 		// Bearer still up to date.  Remember that it's waiting for
       
   417 		// an update.
       
   418 		iMlscUpdatePending = ETrue;
       
   419 		}
       
   420 	}
       
   421 
       
   422 void CRemConMediaBrowseTargetBase::ProcessGetItemAttributes(const TDesC8& aData)
       
   423 	{
       
   424 	TRemConFolderScope scope;
       
   425 	TRemConItemUid item;
       
   426 	TUint16 uidCounter;
       
   427 	TInt err = ParseGetItemAttributesRequest(aData, scope, item, uidCounter);
       
   428 	if (err != KErrNone)
       
   429 	    {
       
   430 	    SendGetItemAttributesResponse(err, KNullDesC8);
       
   431 	    return;
       
   432 	    }
       
   433 	
       
   434 	iAttributeIterator.Start();	
       
   435 	iInProgress = ETrue;
       
   436 	iGetItemAttributes = ETrue;	
       
   437 	TInt result = KErrNone;
       
   438 	if(scope == ENowPlayingFolder)
       
   439 		{
       
   440 		if (!DatabaseAware() && (0 == uidCounter))//Database UnAware
       
   441 			{
       
   442 			result = iRcdunpbo->MrcdunpboGetItem(item, iAttributeIterator);
       
   443 			}
       
   444 		else if (DatabaseAware() && (uidCounter > 0))
       
   445 			{
       
   446 			result = iRcdanpbo->MrcdanpboGetItem(item, iAttributeIterator, uidCounter);
       
   447 			}
       
   448 		else
       
   449 			{
       
   450 			result = KErrAvrcpAirInvalidParameter;
       
   451 			}
       
   452 		}
       
   453 	else
       
   454 		{
       
   455 		if (!DatabaseAware() && (0 == uidCounter))//Database UnAware
       
   456 			{
       
   457 			result = iRcdumlbo->MrcdumlboGetItem(scope, item, iAttributeIterator);
       
   458 			}
       
   459 		else if (DatabaseAware() && (uidCounter > 0))
       
   460 			{
       
   461 			result = iRcdamlbo->MrcdamlboGetItem(scope, item, iAttributeIterator, 
       
   462 					                     uidCounter);
       
   463 			}
       
   464 		else
       
   465 			{
       
   466 			result = KErrAvrcpAirInvalidParameter;
       
   467 			}
       
   468 		}
       
   469 	
       
   470 	// The call back function returns error.
       
   471 	if (result != KErrNone)
       
   472 		{
       
   473 		SendGetItemAttributesResponse(result, KNullDesC8);
       
   474 		}
       
   475 	}
       
   476 
       
   477 void CRemConMediaBrowseTargetBase::SendGetItemAttributesResponse(TInt aResult, const TDesC8& aData)
       
   478 	{
       
   479 	if(aResult != KErrNone)
       
   480 		{
       
   481 		SendError(EMbGetItemAttributes, EGetItemAttributesOperationId, aResult);
       
   482 		}
       
   483 	else
       
   484 		{
       
   485 		InterfaceSelector().SendBulkUnreliable(
       
   486 				TUid::Uid(KRemConMediaBrowseApiUid),
       
   487 				EGetItemAttributesOperationId, aData);
       
   488 		}
       
   489 	
       
   490 	iInProgress = EFalse;
       
   491 	iGetItemAttributes = EFalse;
       
   492 	iMediaAttributeIds.Reset();
       
   493 	iGiaResponse->Close();
       
   494 	
       
   495 	if (!iMsgQueue->IsEmpty())
       
   496 		{
       
   497 		iNextMessageCallBack->CallBack();
       
   498 		}
       
   499 	}
       
   500 
       
   501 void CRemConMediaBrowseTargetBase::ProcessChangePath(const TDesC8& aData)
       
   502 	{
       
   503 	// Try to read the incoming request
       
   504 	TInt error = KErrNone;
       
   505 	RRemConChangePathRequest request;
       
   506 	TRAP(error, request.ReadL(aData));
       
   507 
       
   508 	// Couldn't parse the request; tell them it was invalid
       
   509 	if (error != KErrNone)
       
   510 		{
       
   511 	    SendError(EMbChangePath, EChangePathOperationId, KErrAvrcpAirInvalidParameter);
       
   512 	    return;
       
   513 		}
       
   514 
       
   515 	if(request.iDirection == AvrcpBrowsing::KUp)
       
   516 		{
       
   517 		if (DatabaseAware() && (request.iUidCounter > 0))
       
   518 			{
       
   519 			iRcdamlbo->MrcdamlboFolderUp(request.iUidCounter);
       
   520 			}
       
   521 		else if (!DatabaseAware() && (0 == request.iUidCounter))
       
   522 			{
       
   523 			iRcdumlbo->MrcdumlboFolderUp();
       
   524 			}
       
   525 		else
       
   526 			{
       
   527 			SendError(EMbChangePath, EChangePathOperationId, KErrAvrcpAirInvalidParameter);
       
   528 			}
       
   529 		}
       
   530 	else if(request.iDirection == AvrcpBrowsing::KDown)
       
   531 		{
       
   532 		if (DatabaseAware() && (request.iUidCounter > 0))
       
   533 			{
       
   534 			iRcdamlbo->MrcdamlboFolderDown(request.iElement, request.iUidCounter);
       
   535 			}
       
   536 		else if (!DatabaseAware() && (0 == request.iUidCounter))
       
   537 			{
       
   538 			iRcdumlbo->MrcdumlboFolderDown(request.iElement);
       
   539 			}
       
   540 		else
       
   541 			{
       
   542 			SendError(EMbChangePath, EChangePathOperationId, KErrAvrcpAirInvalidParameter);
       
   543 			}
       
   544 		}
       
   545 	else
       
   546 		{
       
   547 		SendError(EMbChangePath, EChangePathOperationId, KErrAvrcpAirInvalidDirection);
       
   548 		}
       
   549 	}
       
   550 
       
   551 void CRemConMediaBrowseTargetBase::SendSearchResponse(TInt aResult, TUint aNumberItemsFound, TUint16 aMediaLibraryStateCookie)
       
   552 	{	
       
   553 	iSearchString.Close();
       
   554 	
       
   555 	// format the response in a RRemConSearchResponse
       
   556 	RRemConMediaErrorResponse errResponse;
       
   557 	RRemConSearchResponse response;
       
   558 	TInt symbianError = errResponse.SymbianErrorCheck(aResult);
       
   559 	
       
   560 	response.iStatus = errResponse.SymbianErrToStatus(symbianError);	
       
   561 	response.iPduId = AvrcpBrowsing::ESearch;//0x80
       
   562 	response.iUidCounter = aMediaLibraryStateCookie;
       
   563 	response.iNumberItems = aNumberItemsFound;
       
   564 	TRAPD(error, response.WriteL(iOutBuf));
       
   565 	if (error == KErrNone)
       
   566 		{
       
   567 		// send the response back to the CT
       
   568 		error = InterfaceSelector().SendBulkUnreliable(
       
   569 				TUid::Uid(KRemConMediaBrowseApiUid),
       
   570 				ESearchOperationId,  iOutBuf );
       
   571 		}
       
   572 	
       
   573 	//Search operatin complete.
       
   574 	iSearchInProgress = EFalse;
       
   575 	}
       
   576 
       
   577 void CRemConMediaBrowseTargetBase::ProcessSearch(const TDesC8& aData)
       
   578 	{
       
   579 	// Don't trouble the client with this if they've informed us they don't
       
   580 	// support it
       
   581 	if (!iSearchSupported)
       
   582 		{
       
   583 		return SendSearchResponse(KErrAvrcpAirSearchNotSupported, 0, 0);
       
   584 		}
       
   585 	
       
   586 	// We know a search operation is in progress
       
   587 	if (iSearchInProgress)
       
   588 		{
       
   589 		return SendSearchResponse(KErrAvrcpAirSearchInProgress, 0, 0);
       
   590 		}
       
   591 		
       
   592 	// Try to read the incoming request
       
   593 	TInt error = KErrNone;
       
   594 	RRemConSearchRequest request;
       
   595 	TRAP(error, request.ReadL(aData));
       
   596 
       
   597 	// Couldn't parse the request; tell them it was invalid
       
   598 	if (error != KErrNone)
       
   599 		{
       
   600 		error = (error == KErrNoMemory) ? 
       
   601 				KErrAvrcpAirInternalError : KErrAvrcpAirInvalidParameter;
       
   602 		
       
   603 		return SendSearchResponse(error, 0, 0);
       
   604 		}
       
   605 
       
   606 	// Check the character set
       
   607 	if (request.iCharset != KUtf8MibEnum)
       
   608 		{
       
   609 		iSearchInProgress = EFalse;
       
   610 		return SendSearchResponse(KErrAvrcpAirInvalidParameter, 0, 0);
       
   611 		}
       
   612 	
       
   613 	iSearchString.Close();
       
   614 	iSearchString.Assign(request.iSearchString);
       
   615 	//iSearchString has taken ownership of request's search string.
       
   616 	request.iSearchString.Assign(NULL);
       
   617 	
       
   618 	iSearchInProgress = ETrue;
       
   619 	
       
   620 	if(DatabaseAware())
       
   621 		{
       
   622 		iRcdamlbo->MrcdamlboSearch(iSearchString);
       
   623 		}
       
   624 	else
       
   625 		{
       
   626 		iRcdumlbo->MrcdumlboSearch(iSearchString);
       
   627 		}
       
   628 	
       
   629 	request.Close();
       
   630 	}
       
   631 
       
   632 void CRemConMediaBrowseTargetBase::ProcessGetPath(const TDesC8& aData)
       
   633 	{
       
   634 	iGflResponse->iMaxResponse = *(reinterpret_cast<const TInt*>(aData.Ptr()));
       
   635 
       
   636 	if(DatabaseAware())
       
   637 		{
       
   638 		iRcdamlbo->MrcdamlboGetPath(iGetPathResponse->iPath);
       
   639 		}
       
   640 	else
       
   641 		{
       
   642 		iRcdumlbo->MrcdumlboGetPath(iGetPathResponse->iPath);
       
   643 		}
       
   644 	}
       
   645 
       
   646 void CRemConMediaBrowseTargetBase::ProcessGetFolderItems(const TDesC8& aData)
       
   647 	{
       
   648 	// The bearer is responsible for ensuring we have been supplied with response
       
   649 	// max size before sending us any requests
       
   650 	__ASSERT_DEBUG(iGflResponse->iMaxResponse != 0, MediaBrowseFault::Fault(ERequestWithoutMaxResponseBeingSet));
       
   651 	
       
   652 	iInProgress = ETrue;
       
   653 	iGetFolderListing = ETrue;
       
   654 	
       
   655 	RRemConGetFolderItemsRequest request;
       
   656 	TRAPD(err, request.ReadL(aData));
       
   657 	if(err != KErrNone)
       
   658 		{
       
   659 		request.Close();
       
   660 		SendGetFolderItemsResponse(KErrAvrcpAirInvalidParameter, KNullDesC8);
       
   661 		return;
       
   662 		}
       
   663 
       
   664 	if(request.iScope == AvrcpBrowsing::KSearchScope && !iSearchSupported)
       
   665 	    {
       
   666         request.Close();
       
   667         SendGetFolderItemsResponse(KErrAvrcpAirSearchNotSupported, KNullDesC8);
       
   668         return;
       
   669         }
       
   670 	
       
   671 	if (request.CopyAttributes(iMediaAttributeIds) != KErrNone)
       
   672 		{
       
   673 		request.Close();
       
   674 		SendGetFolderItemsResponse(KErrAvrcpAirInternalError, KNullDesC8);
       
   675 		return;
       
   676 		}
       
   677 	iAttributeIterator.Start();
       
   678 
       
   679 	if(request.iScope == AvrcpBrowsing::KVirtualFilesystemScope)
       
   680 		{
       
   681 		iScope = EBrowseFolder;
       
   682 		}
       
   683 	else if(request.iScope == AvrcpBrowsing::KNowPlayingScope)
       
   684 		{
       
   685 		iScope = ENowPlayingFolder;
       
   686 		}
       
   687 	else if(request.iScope == AvrcpBrowsing::KSearchScope)
       
   688         {
       
   689         iScope = ESearchResultFolder;
       
   690         }
       
   691 	else
       
   692 		{
       
   693 		request.Close();
       
   694 		SendGetFolderItemsResponse(KErrAvrcpAirInvalidScope, KNullDesC8);
       
   695 		return;
       
   696 		}
       
   697 	
       
   698 	if (request.iStartItem > request.iEndItem)
       
   699 		{
       
   700 		request.Close();
       
   701 		SendGetFolderItemsResponse(KErrAvrcpAirRangeOutOfBounds, KNullDesC8);
       
   702 		return;
       
   703 		}
       
   704 	
       
   705 	if(iScope == ENowPlayingFolder)
       
   706 		{
       
   707 		if(DatabaseAware())
       
   708 			{
       
   709 			iRcdanpbo->MrcdanpboGetFolderListing(request.iStartItem, request.iEndItem);
       
   710 			}
       
   711 		else
       
   712 			{
       
   713 			iRcdunpbo->MrcdunpboGetFolderListing(request.iStartItem, request.iEndItem);
       
   714 			}
       
   715 		}
       
   716 	else
       
   717 		{
       
   718 		if(DatabaseAware())
       
   719 			{
       
   720 			iRcdamlbo->MrcdamlboGetFolderListing(iScope,request.iStartItem, request.iEndItem);
       
   721 			}
       
   722 		else
       
   723 			{
       
   724 			iRcdumlbo->MrcdumlboGetFolderListing(iScope,request.iStartItem, request.iEndItem);
       
   725 			}
       
   726 		}
       
   727 	
       
   728 	request.Close();
       
   729 	}
       
   730 
       
   731 void CRemConMediaBrowseTargetBase::SendGetFolderItemsResponse(TInt aResult, const TDesC8& aData)
       
   732 	{
       
   733 	if(aResult != KErrNone)
       
   734 		{
       
   735 		SendError(EMbGetFolderItems, EGetFolderItemsOperationId, aResult);
       
   736 		}
       
   737 	else
       
   738 		{
       
   739 		InterfaceSelector().SendBulkUnreliable(
       
   740 				TUid::Uid(KRemConMediaBrowseApiUid),
       
   741 				EGetFolderItemsOperationId, aData);
       
   742 		}
       
   743 	
       
   744 	iInProgress = EFalse;
       
   745 	iGetFolderListing = EFalse;
       
   746 	iMediaAttributeIds.Reset();
       
   747 	iGflResponse->Close();
       
   748 	
       
   749 	iNextItemCallBack->Cancel();
       
   750 	
       
   751 	if (!iMsgQueue->IsEmpty())
       
   752 		{
       
   753 		iNextMessageCallBack->CallBack();
       
   754 		}
       
   755 	}
       
   756 
       
   757 TInt CRemConMediaBrowseTargetBase::NextMessageCb(TAny* aThis)
       
   758 	{
       
   759 	static_cast<CRemConMediaBrowseTargetBase*>(aThis)->DoNextMessage();
       
   760 	return KErrNone;
       
   761 	}
       
   762 
       
   763 void CRemConMediaBrowseTargetBase::DoNextMessage()
       
   764 	{
       
   765 	__ASSERT_DEBUG(!iMsgQueue->IsEmpty(), MediaBrowseFault::Fault(EUnexpectedNextMessageCallback));
       
   766 	CRemConQueuedMessage* msg = iMsgQueue->First();
       
   767 	iMsgQueue->Remove(*msg);
       
   768 	
       
   769 	switch (msg->iOperationId)
       
   770 		{
       
   771 		case EGetFolderItemsOperationId:
       
   772 			ProcessGetFolderItems(msg->Data());
       
   773 			break;
       
   774 		case EGetItemAttributesOperationId:
       
   775 			ProcessGetItemAttributes(msg->Data());
       
   776 			break;
       
   777 		default:
       
   778 			__ASSERT_DEBUG(EFalse, MediaBrowseFault::Fault(EUnexpectedNextMessageCallback));
       
   779 			break;
       
   780 		}
       
   781 	delete msg;
       
   782 	}
       
   783 
       
   784 void CRemConMediaBrowseTargetBase::SendMediaLibraryStateCookieUpdateResponse(TUint16 aMediaLibraryStateCookie)
       
   785 	{
       
   786 	LOG_FUNC
       
   787 	
       
   788 	TUint16 newValue = DatabaseAware() ? aMediaLibraryStateCookie : KDatabaseUnawareUidCounter;
       
   789 
       
   790 	TInt error = KErrNone;
       
   791 	RRemConUidsChangedResponse response;
       
   792 	response.iUidCounter = newValue;
       
   793 	TRAP(error, response.WriteL(iOutBuf));
       
   794 
       
   795 	if (error == KErrNone)
       
   796 		{
       
   797 		// send the response back to the CT
       
   798 		error = InterfaceSelector().SendBulkUnreliable(
       
   799 				TUid::Uid(KRemConMediaBrowseApiUid),
       
   800 				EMediaLibraryStateCookieUpdateOperationId, iOutBuf);
       
   801 		
       
   802 		iLastMlscUpdate = newValue;
       
   803 		iMlscUpdatePending = EFalse;
       
   804 		}
       
   805 	// otherwise we couldn't update the client.  Leave our state with the update
       
   806 	// pending then we'll try again next time the client tells us state has 
       
   807 	// changed.  
       
   808 	}
       
   809 
       
   810 void CRemConMediaBrowseTargetBase::SendChangePathResponse(TUint aItemCount, 
       
   811 		TInt aResult)
       
   812 	{
       
   813 	if (aResult != KErrNone)
       
   814 		{
       
   815 		return SendError(EMbChangePath, EChangePathOperationId, aResult);
       
   816 		}
       
   817 	
       
   818 	TInt error = KErrNone;
       
   819 
       
   820 	// Format the response in a RRemConChangePathResponse
       
   821 	RRemConChangePathResponse response;
       
   822 	response.iStatus = KErrAvrcpAirBase - KErrAvrcpAirSuccess;//0x4
       
   823 	response.iNumberItems = aItemCount;
       
   824 	
       
   825 	RBuf8 responseBuf;
       
   826 	error = responseBuf.Create(KMediaBrowseOutBufMaxLength);
       
   827 	if (error != KErrNone)
       
   828 		{
       
   829 		responseBuf.Close();
       
   830 		SendError(EMbChangePath, EChangePathOperationId, KErrAvrcpAirInternalError);
       
   831 		return;
       
   832 		}
       
   833 	
       
   834 	response.iPduId = AvrcpBrowsing::EChangePath;
       
   835 	TRAP(error, response.WriteL(responseBuf));
       
   836 	if (error == KErrNone)
       
   837 		{
       
   838 		// send the response back to the CT
       
   839 		error = InterfaceSelector().SendBulkUnreliable(
       
   840 				TUid::Uid(KRemConMediaBrowseApiUid),
       
   841 				EChangePathOperationId, responseBuf );
       
   842 		}
       
   843 	
       
   844 	responseBuf.Close();
       
   845 	}
       
   846 
       
   847 TInt CRemConMediaBrowseTargetBase::NextItemCallBack(TAny* aThis)
       
   848 	{
       
   849 	static_cast<CRemConMediaBrowseTargetBase*>(aThis)->RequestNextItem();
       
   850 	return KErrNone;
       
   851 	}
       
   852 
       
   853 void CRemConMediaBrowseTargetBase::RequestNextItem()
       
   854 	{
       
   855 	TInt err = KErrNone;
       
   856 	TInt result = KErrNone;
       
   857 	RBuf8 responseBuf;
       
   858 	
       
   859 	// If true, indicate that we have not got all the items requested, 
       
   860 	// so going on. 
       
   861 	// There are some array elements accessed by [] as follows without 
       
   862 	// checking range for it is done in RequestNextItem function.
       
   863 	if ( iGflResponse->RequestNextItem(err, responseBuf, 
       
   864 			iGflResponse->iUidCounter) )
       
   865 		{
       
   866 		TBool folderItem = EFalse;
       
   867 		if (AvrcpBrowsing::EFolderItem == iGflResponse->iItems[iGflResponse->iCurrentItem].iType)
       
   868 			{
       
   869 			folderItem = ETrue;
       
   870 			}
       
   871 		iAttributeIterator.Start();	
       
   872 		if(iScope == ENowPlayingFolder)
       
   873 			{
       
   874 			if(DatabaseAware())
       
   875 				{
       
   876 				result = iRcdanpbo->MrcdanpboGetItem(
       
   877 			    		iGflResponse->iItems[iGflResponse->iCurrentItem].iUid,
       
   878 			    		folderItem ? iNullIterator : iAttributeIterator,
       
   879 			    		iGflResponse->iUidCounter);
       
   880 				}
       
   881 			else
       
   882 				{
       
   883 				result = iRcdunpbo->MrcdunpboGetItem( 
       
   884 			    		iGflResponse->iItems[iGflResponse->iCurrentItem].iUid,
       
   885 			    		folderItem ? iNullIterator : iAttributeIterator);
       
   886 				}
       
   887 			}
       
   888 		else
       
   889 			{
       
   890 			if(DatabaseAware())
       
   891 				{
       
   892 				result = iRcdamlbo->MrcdamlboGetItem(iScope,
       
   893 			    		iGflResponse->iItems[iGflResponse->iCurrentItem].iUid,
       
   894 			    		folderItem ? iNullIterator : iAttributeIterator,
       
   895 			    		iGflResponse->iUidCounter);
       
   896 				}
       
   897 			else
       
   898 				{
       
   899 				result = iRcdumlbo->MrcdumlboGetItem(iScope, 
       
   900 			    		iGflResponse->iItems[iGflResponse->iCurrentItem].iUid,
       
   901 			    		folderItem ? iNullIterator : iAttributeIterator);
       
   902 				}
       
   903 			}
       
   904 		
       
   905 		// The call back function reutrns error.
       
   906 		if (result != KErrNone)
       
   907 			{
       
   908 			SendGetFolderItemsResponse(result, KNullDesC8);
       
   909 			}
       
   910 		}
       
   911 	// If comes here, indicate that we stop requesting the next item
       
   912 	// which means two possibilities:
       
   913 	// 1. Success: Have got all the items we want.
       
   914 	// 2. Error: Error occured internally.
       
   915 	else if ( err == KErrNone ) //Possibility 1.
       
   916 		{
       
   917 		SendGetFolderItemsResponse(KErrNone, responseBuf);
       
   918 		}
       
   919 	else // Possibility 2.
       
   920 		{
       
   921 		SendGetFolderItemsResponse(KErrAvrcpAirInternalError, KNullDesC8);
       
   922 		}
       
   923 	responseBuf.Close();
       
   924 	}
       
   925 
       
   926 void CRemConMediaBrowseTargetBase::DoItemComplete(TInt aResult)
       
   927 	{
       
   928 	if (aResult != KErrNone)
       
   929 		{
       
   930 		SendGetFolderItemsResponse(aResult, KNullDesC8);
       
   931 		}
       
   932 	else
       
   933 		{
       
   934 		// We have to put an async break in here - otherwise if large
       
   935 		// numbers of items are requested we could overflow the stack
       
   936 		iNextItemCallBack->CallBack();
       
   937 		}
       
   938 	}
       
   939 
       
   940 void CRemConMediaBrowseTargetBase::SendError(TUint8 aPduId, 
       
   941 		TUint aOperationId, 
       
   942 		TInt aError)
       
   943 	{
       
   944 	TInt error = KErrNone;
       
   945 	RRemConMediaErrorResponse response;
       
   946 	response.iPduId = aPduId;
       
   947 	response.iStatus = RAvrcpIPC::SymbianErrToStatus(aError);
       
   948 	TRAP(error, response.WriteL(iOutBuf));
       
   949 	if (error == KErrNone)
       
   950 		{
       
   951 		InterfaceSelector().SendBulkUnreliable(
       
   952 				TUid::Uid(KRemConMediaBrowseApiUid),
       
   953 				aOperationId, iOutBuf);
       
   954 		}
       
   955 	}
       
   956 
       
   957 /** 
       
   958 Sets an attribute value for the requested item.
       
   959 */
       
   960 TInt CRemConMediaBrowseTargetBase::DoAttributeValue(
       
   961 		TMediaAttributeId aAttributeId, 
       
   962 		const TDesC8& aAttributeData )
       
   963 	{
       
   964 	iSetAttributeValue = ETrue;
       
   965 	
       
   966 	REAResponse resp;
       
   967 	resp.iAttributeId = aAttributeId;
       
   968 	resp.iCharset = KUtf8MibEnum;
       
   969 	resp.iStringLen = aAttributeData.Length();
       
   970 	resp.iString = aAttributeData.Alloc();
       
   971 	if (!resp.iString)
       
   972 		{
       
   973 		iSetAttributeValue = EFalse;
       
   974 		return KErrNoMemory;
       
   975 		}
       
   976 	TInt status = KErrNone;
       
   977 	if(iGiaResponse->Size() + resp.iStringLen < iGflResponse->iMaxResponse)
       
   978 		{
       
   979 		status = iGiaResponse->iAttributes.Append(resp);
       
   980 		if (status != KErrNone)
       
   981 			{
       
   982 			iSetAttributeValue = EFalse;
       
   983 			resp.Close();  // make sure heap string is de-allocated
       
   984 			}
       
   985 		}
       
   986 	
       
   987 	return status;
       
   988 	}
       
   989 
       
   990 /**
       
   991 Signals that all attributes requested has been supplied.
       
   992 */
       
   993  void CRemConMediaBrowseTargetBase::DoAllAttributesCompleted(TInt aResult)
       
   994 	{
       
   995 	TInt error = KErrNone;
       
   996 	__ASSERT_DEBUG(((aResult != KErrNone) || ((aResult == KErrNone) && iSetAttributeValue)),
       
   997 			MediaBrowseFault::Fault(EResultErrorCodeMismatch));
       
   998 	
       
   999 	if (aResult == KErrNone)
       
  1000 		{
       
  1001 		// Finalise response; update number of attributes returned
       
  1002 		iGiaResponse->iNumberAttributes = iGiaResponse->iAttributes.Count();
       
  1003 		}
       
  1004 
       
  1005 	// Allocate a buffer for the formatted message
       
  1006 	RBuf8 messageBuffer;	
       
  1007 	TInt bufferSize = 
       
  1008 	(aResult == KErrNone) ? iGiaResponse->Size() : KBrowseResponseBaseLength;
       
  1009 	
       
  1010 	if ( messageBuffer.Create(bufferSize) != KErrNone )
       
  1011 		{
       
  1012 		SendGetItemAttributesResponse(KErrAvrcpAirInternalError, KNullDesC8);
       
  1013 		}
       
  1014 	else
       
  1015 		{
       
  1016 		// Send the result back to the CT
       
  1017 		iGiaResponse->iPduId = AvrcpBrowsing::EGetItemAttributes; // 0x73
       
  1018 		iGiaResponse->iStatus = RAvrcpIPC::SymbianErrToStatus(aResult);
       
  1019 		
       
  1020 		TRAP(error, iGiaResponse->WriteL(messageBuffer));
       
  1021 		if (error == KErrNone)
       
  1022 			{
       
  1023 			SendGetItemAttributesResponse(KErrNone, messageBuffer);
       
  1024 			}
       
  1025 		else
       
  1026 			{
       
  1027 			SendGetItemAttributesResponse(KErrAvrcpAirInternalError, KNullDesC8);
       
  1028 			}
       
  1029 		}
       
  1030 	messageBuffer.Close();
       
  1031 	}
       
  1032 
       
  1033 TInt CRemConMediaBrowseTargetBase::ItemAttributesResult(
       
  1034 		const TArray<TMediaElementAttribute>& aAttributes)
       
  1035 	{
       
  1036 	TInt error = KErrNone;
       
  1037 	TMediaAttributeId attributeId;
       
  1038 	for (TInt i = 0; i < aAttributes.Count(); i++)
       
  1039 		{
       
  1040 		// check that the values supplied were requested
       
  1041 		attributeId = aAttributes[i].iAttributeId;
       
  1042 		if ( KErrNotFound == iMediaAttributeIds.Find(attributeId) )
       
  1043 			{
       
  1044 			//Omit the invalid ones
       
  1045 			continue;
       
  1046 			}
       
  1047 		
       
  1048 		error = DoAttributeValue(attributeId, *aAttributes[i].iString);
       
  1049 		if (error != KErrNone)
       
  1050 			{
       
  1051 			break;
       
  1052 			}
       
  1053 		}
       
  1054 	
       
  1055 	return error;
       
  1056 	}
       
  1057 
       
  1058 void CRemConMediaBrowseTargetBase::AddToOperationQueue(TUint8 aPduId,
       
  1059 		TInt aOperationId, 
       
  1060 		const TDesC8& aData)
       
  1061 	{
       
  1062 	CRemConQueuedMessage* msg = NULL;
       
  1063 	TRAPD(err, msg = CRemConQueuedMessage::NewL(
       
  1064 			TUid::Uid(KRemConMediaBrowseApiUid), aData, aOperationId));			
       
  1065 	if (err == KErrNone)
       
  1066 		{
       
  1067 		iMsgQueue->AddLast(*msg);
       
  1068 		}
       
  1069 	else
       
  1070 		{
       
  1071 		SendError(aPduId, aOperationId, KErrAvrcpAirInternalError);
       
  1072 		}
       
  1073 	}
       
  1074 
       
  1075 TInt CRemConMediaBrowseTargetBase::ParseGetItemAttributesRequest(
       
  1076 		const TDesC8& aData,
       
  1077 		TRemConFolderScope& aScope,
       
  1078 		TRemConItemUid& aItemUid,
       
  1079 		TUint16& aMediaLibraryStateCookie)
       
  1080 	{
       
  1081 	// Try to read the incoming request
       
  1082 	TInt error = KErrNone;
       
  1083 	RRemConGetItemAttributesRequest request;
       
  1084 	TRAP(error, request.ReadL(aData));
       
  1085 
       
  1086 	// Couldn't parse the request;tell them it was invalid
       
  1087 	// Specification says unique id must not be 0x0
       
  1088 	if (error != KErrNone || request.iElement == 0)
       
  1089 		{
       
  1090 		request.Close();
       
  1091 		return KErrAvrcpAirInvalidParameter;
       
  1092 		}
       
  1093 
       
  1094 	if (request.iNumberAttributes == 0)
       
  1095 		{
       
  1096 		// spec says this is a request for all attribs
       
  1097 		// current spec has 7 specified (0x01 to 0x07)
       
  1098 		for (TInt i = 1; i <= KMediaAttributeNum; i++)
       
  1099 			{
       
  1100 			if (iMediaAttributeIds.Append(static_cast<TMediaAttributeId>(i))
       
  1101 					!= KErrNone)
       
  1102 				{
       
  1103 				request.Close();
       
  1104 				return KErrAvrcpAirInternalError;
       
  1105 				}
       
  1106 			}
       
  1107 		}
       
  1108 	else
       
  1109 		{
       
  1110 		// No need to check 
       
  1111 		// request.iNumberAttributes == request.iAttributes.Count()
       
  1112 		// as this must be correct or request.ReadL(aData) leaves
       
  1113 		TUint8 value;
       
  1114 		TMediaAttributeId attributeid;
       
  1115 		for (TInt i = 0; i < request.iNumberAttributes; i++)
       
  1116 			{
       
  1117 			value = request.iAttributes[i];
       
  1118 			if (value > 0 && value <= KMaxMediaAttributeValue )
       
  1119 				{
       
  1120 				attributeid = static_cast<TMediaAttributeId>(value);
       
  1121 				if (iMediaAttributeIds.Append(attributeid) != KErrNone)
       
  1122 					{
       
  1123 					request.Close();
       
  1124 					return KErrAvrcpAirInternalError;
       
  1125 					}
       
  1126 				}
       
  1127 			}
       
  1128 		}
       
  1129 	// Check that some valid attribute ids have been found
       
  1130 	if (iMediaAttributeIds.Count() == 0)
       
  1131 		{
       
  1132 		request.Close();
       
  1133 		return KErrAvrcpAirInvalidParameter;
       
  1134 		}
       
  1135 		
       
  1136 	if(request.iScope == AvrcpBrowsing::KSearchScope)
       
  1137 		{
       
  1138 		aScope = ESearchResultFolder;
       
  1139 		}
       
  1140 	else if(request.iScope == AvrcpBrowsing::KVirtualFilesystemScope)
       
  1141 		{
       
  1142 		aScope = EBrowseFolder;
       
  1143 		}
       
  1144 	else if (request.iScope == AvrcpBrowsing::KNowPlayingScope)
       
  1145 		{
       
  1146 		aScope = ENowPlayingFolder;
       
  1147 		}
       
  1148 	else
       
  1149 		{
       
  1150 		request.Close();
       
  1151 		return KErrAvrcpAirInvalidScope;
       
  1152 		}
       
  1153 	
       
  1154 	aItemUid = request.iElement;
       
  1155 	aMediaLibraryStateCookie = request.iUidCounter;
       
  1156 	
       
  1157 	request.Close();
       
  1158 	return KErrNone;
       
  1159 	}
       
  1160 
       
  1161 void CRemConMediaBrowseTargetBase::ProcessMediaElementItemResult(
       
  1162 		const TRemConItemUid& aMediaID, 
       
  1163 		const TDesC8& aMediaName,
       
  1164 		TMediaItemType aMediaType, 
       
  1165 		const TArray<TMediaElementAttribute>& aAttributes,
       
  1166 		TInt aResult)
       
  1167 	{
       
  1168 	TInt internalError = KErrNone;
       
  1169 	if (aResult == KErrNone)
       
  1170 		{
       
  1171 		__ASSERT_DEBUG(aMediaType < AvrcpBrowsing::KMediaTypeReserved, MediaBrowsePanic::Panic(EInvalidMediaType));
       
  1172 
       
  1173 		RItem& item = iGflResponse->iItems[iGflResponse->iCurrentItem];
       
  1174 		if (item.iUid == aMediaID)
       
  1175 			{
       
  1176 			item.iType = AvrcpBrowsing::EMediaElement;
       
  1177 			item.iCharset = KUtf8MibEnum;
       
  1178 			
       
  1179 			item.iName = aMediaName.Alloc();		
       
  1180 			internalError = (!item.iName) ? KErrNoMemory : internalError;
       
  1181 			
       
  1182 			if (internalError == KErrNone)
       
  1183 				{
       
  1184 				item.iNameLength = aMediaName.Length();
       
  1185 				item.iMediaType = static_cast<AvrcpBrowsing::TFolderType>(aMediaType);
       
  1186 				item.iNumberAttributes = aAttributes.Count();
       
  1187 				item.iLength = KMediaElementItemBaseLength + item.iNameLength;
       
  1188 				TInt attributeCount = aAttributes.Count();
       
  1189 				REAResponse attribute;
       
  1190 				for (TInt i = 0; i < attributeCount; i++)
       
  1191 					{
       
  1192 					// Check that the values supplied were requested
       
  1193 					if (KErrNotFound == iMediaAttributeIds.Find(aAttributes[i].iAttributeId))
       
  1194 						{
       
  1195 						//Omit the invalid ones
       
  1196 						continue;
       
  1197 						}
       
  1198 					
       
  1199 					attribute.iAttributeId = aAttributes[i].iAttributeId;				
       
  1200 					attribute.iString = aAttributes[i].iString->Alloc();
       
  1201 					internalError = (!attribute.iString) ? KErrNoMemory : internalError;
       
  1202 					if (internalError == KErrNone)
       
  1203 						{
       
  1204 						attribute.iCharset = KUtf8MibEnum;
       
  1205 						attribute.iStringLen = attribute.iString->Length();
       
  1206 						item.iAttributes.Append(attribute);
       
  1207 						
       
  1208 						item.iLength += 
       
  1209 						KAttributeBaseLength + attribute.iString->Length();
       
  1210 						}
       
  1211 					else
       
  1212 						{
       
  1213 						//it's useless to continue as there is an allocation issue
       
  1214 						break;
       
  1215 						}
       
  1216 					}
       
  1217 				}
       
  1218 			}
       
  1219 		else
       
  1220 			{
       
  1221 			internalError = KErrArgument;
       
  1222 			}
       
  1223 		}
       
  1224 	
       
  1225 	aResult = 
       
  1226 	(KErrNone == internalError)? aResult : KErrAvrcpAirInternalError;
       
  1227 	
       
  1228 	DoItemComplete(aResult);
       
  1229 	}
       
  1230 
       
  1231 void CRemConMediaBrowseTargetBase::ProcessFolderItemResult(
       
  1232 		const TRemConItemUid& aFolderID,
       
  1233 		const TDesC8& aFolderName, 
       
  1234 		TFolderItemType aFolderType, 
       
  1235 		TFolderItemPlayable aPlayable,
       
  1236 		TInt aResult)
       
  1237 	{
       
  1238 	TInt internalError = KErrNone;
       
  1239 	if (aResult == KErrNone)
       
  1240 	    {
       
  1241 		__ASSERT_DEBUG(aFolderType < AvrcpBrowsing::EFolderTypeReserved, MediaBrowsePanic::Panic(EInvalidFolderType));
       
  1242 		__ASSERT_DEBUG(aPlayable < AvrcpBrowsing::KPlayableReserved, MediaBrowsePanic::Panic(EInvalidPlayableValue));
       
  1243 		
       
  1244 		RItem& item = iGflResponse->iItems[iGflResponse->iCurrentItem];
       
  1245 		if (item.iUid == aFolderID)
       
  1246 			{
       
  1247 			item.iType = AvrcpBrowsing::EFolderItem;
       
  1248 			item.iCharset = KUtf8MibEnum;
       
  1249 			
       
  1250 			item.iName = aFolderName.Alloc();
       
  1251 			internalError = (!item.iName) ? KErrNoMemory : internalError;
       
  1252 					
       
  1253 			item.iNameLength = aFolderName.Length();
       
  1254 			
       
  1255 			item.iFolderType = 
       
  1256 			static_cast<AvrcpBrowsing::TFolderType>(aFolderType);
       
  1257 			
       
  1258 			item.iPlayable = aPlayable;
       
  1259 			item.iLength = KFolderItemBaseLength + item.iNameLength;
       
  1260 			}
       
  1261 		else
       
  1262 			{
       
  1263 			internalError = KErrArgument;
       
  1264 			}
       
  1265 	    }
       
  1266 			                        
       
  1267 	aResult = (internalError == KErrNone) ? aResult : KErrAvrcpAirInternalError;
       
  1268 	
       
  1269 	DoItemComplete(aResult);
       
  1270 	}
       
  1271 
       
  1272 void CRemConMediaBrowseTargetBase::ProcessGetItemAttributesResult(
       
  1273 			const TArray<TMediaElementAttribute>& aAttributes,
       
  1274 			TInt aResult)
       
  1275 	{
       
  1276 	TInt internalError = KErrNone;
       
  1277 	if (aResult == KErrNone)
       
  1278 	    {
       
  1279 	    internalError = ItemAttributesResult(aAttributes);
       
  1280 	    }				
       
  1281 	
       
  1282 	aResult =
       
  1283 	(KErrNone == internalError)? aResult : KErrAvrcpAirInternalError;
       
  1284 	
       
  1285 	DoAllAttributesCompleted(aResult);
       
  1286 	}
       
  1287 
       
  1288 inline TBool CRemConMediaBrowseTargetBase::DatabaseAware() const
       
  1289 	{
       
  1290 	return iRcdanpbo ? ETrue : EFalse;
       
  1291 	}