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