bluetoothappprofiles/avrcp/nowplayingapi/src/remconnowplayingtargetbase.cpp
changeset 70 f5508c13dfe0
parent 67 16e4b9007960
child 71 083fd884d7dd
equal deleted inserted replaced
67:16e4b9007960 70:f5508c13dfe0
     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 <remconmediabrowsetypes.h>
       
    25 #include <remcondatabaseawarenowplayingtargetobserver.h>
       
    26 #include <remcondatabaseunawarenowplayingtargetobserver.h>
       
    27 #include <remcon/remconnowplayingtargetbase.h>
       
    28 #include <remcon/avrcpspec.h>
       
    29 #include <remconinterfaceselector.h>
       
    30 #include <bluetooth/logger.h>
       
    31 
       
    32 #include "mediabrowse.h"
       
    33 #include "nowplaying.h"
       
    34 #include "remconnowplayingfault.h"
       
    35 #include "remconqueuemessage.h"
       
    36 
       
    37 #ifdef __FLOG_ACTIVE
       
    38 _LIT8(KLogComponent, LOG_COMPONENT_REMCONNOWPLAYINGAPI);
       
    39 _LIT8(KLogFormat, "Operation Id = 0x%x, Data Lengh = %d");
       
    40 #endif
       
    41 
       
    42 CRemConNowPlayingTargetBase::CRemConNowPlayingTargetBase(
       
    43 	CRemConInterfaceSelector& aInterfaceSelector,
       
    44 	MRemConDatabaseAwareNowPlayingTargetObserver& aObserver)
       
    45 	: CRemConInterfaceBase(
       
    46 	TUid::Uid(KRemConNowPlayingApiUid),
       
    47 	KMaxLengthNowPlayingMsg,
       
    48 	aInterfaceSelector,
       
    49 	ERemConClientTypeTarget), 
       
    50 	iDaObserver(&aObserver),
       
    51 	iInterfaceSelector(aInterfaceSelector),
       
    52 	iInProgress(EFalse)
       
    53 	{
       
    54 	}
       
    55 		
       
    56 CRemConNowPlayingTargetBase::CRemConNowPlayingTargetBase(
       
    57 	CRemConInterfaceSelector& aInterfaceSelector,
       
    58 	MRemConDatabaseUnawareNowPlayingTargetObserver& aObserver)
       
    59 	: CRemConInterfaceBase(
       
    60 	TUid::Uid(KRemConNowPlayingApiUid),
       
    61 	KMaxLengthNowPlayingMsg,
       
    62 	aInterfaceSelector,
       
    63 	ERemConClientTypeTarget), 
       
    64 	iDuObserver(&aObserver),
       
    65 	iInterfaceSelector(aInterfaceSelector),
       
    66 	iInProgress(EFalse)
       
    67 	{
       
    68 	}
       
    69 	
       
    70 void CRemConNowPlayingTargetBase::BaseConstructL()
       
    71 	{
       
    72 	iMsgQueue = new(ELeave)TRemConMessageQueue;
       
    73 	TCallBack cb(&NextMessageCb, this);
       
    74 	iNextMessageCallBack = new (ELeave) CAsyncCallBack(cb,
       
    75 			CActive::EPriorityStandard);
       
    76 		
       
    77 	iOutBuf.CreateL(KMaxLengthNowPlayingMsg);
       
    78 	
       
    79     // Mandate the following features supported.
       
    80 	RRemConInterfaceFeatures features;
       
    81 	User::LeaveIfError(features.Open());
       
    82 	CleanupClosePushL(features);
       
    83 
       
    84 	features.AddOperationL(EPlayItem);
       
    85 	features.AddOperationL(EAddToNowPlaying);
       
    86 	features.AddOperationL(ERegisterNotification);
       
    87 	
       
    88     CRemConInterfaceBase::BaseConstructL(features);
       
    89     CleanupStack::PopAndDestroy(&features);
       
    90 	}
       
    91 	
       
    92 
       
    93 EXPORT_C CRemConNowPlayingTargetBase::~CRemConNowPlayingTargetBase()
       
    94 	{
       
    95 	iOutBuf.Close();
       
    96 
       
    97 	iNextMessageCallBack->Cancel();
       
    98 	delete iNextMessageCallBack;
       
    99 	
       
   100 	iMsgQueue->Reset();
       
   101 	delete iMsgQueue;
       
   102 	}
       
   103 
       
   104 /** 
       
   105 @internalComponent
       
   106 @released
       
   107 
       
   108 Gets a pointer to a specific interface version.
       
   109 
       
   110 @return A pointer to the interface, NULL if not supported.
       
   111 */
       
   112 TAny* CRemConNowPlayingTargetBase::GetInterfaceIf(TUid aUid)
       
   113 	{
       
   114 	TAny* ret = NULL;
       
   115 	if ( aUid == TUid::Uid(KRemConInterfaceIf2) )
       
   116 		{
       
   117 		ret = reinterpret_cast<TAny*>(
       
   118 			static_cast<MRemConInterfaceIf2*>(this)
       
   119 			);
       
   120 		}
       
   121 
       
   122 	return ret;
       
   123 	}
       
   124 
       
   125 /**
       
   126 Provide a response to the play item command. For database aware clients this 
       
   127 would have been called via MrcdanptoPlayItem(). For database unaware client
       
   128 this would have been called via MrcdunptoPlayItem()
       
   129 
       
   130 The client must call NowPlayingContentChanged() if the content of the now 
       
   131 playing list has been changed after the client successfully plays the item
       
   132 and provides the response with KErrNone through this function.
       
   133 
       
   134 @param aErr The result of play item operation.
       
   135      - KErrNone if the operation was successful.
       
   136      - KErrInvalidMediaLibraryStateCookie if the client is able to maintain 
       
   137        unique UIDs accross the entire virtual filesystem, but the media 
       
   138        library state cookie provided does not match the client's state cookie.
       
   139      - KErrInvalidUid if the uid of the item provided does not refer to any 
       
   140        valid item.
       
   141      - KErrNowPlayingUidIsADirectory if the uid of the item provided refers to
       
   142        a directory which can not be handled by this media player.
       
   143      - KErrNowPlayingMediaInUse if the item is in use and can not be played.
       
   144      - System wide error code otherwise.
       
   145 
       
   146 @see NowPlayingContentChanged()
       
   147 */
       
   148 EXPORT_C void CRemConNowPlayingTargetBase::PlayItemResponse(TInt aErr)
       
   149 	{
       
   150 	TUint8 status = RAvrcpIPC::SymbianErrToStatus(aErr);
       
   151 	SendResponse(status, EPlayItem);
       
   152 	
       
   153 	iInProgress = EFalse;		
       
   154 	if (!iMsgQueue->IsEmpty())
       
   155 		{
       
   156 		iNextMessageCallBack->CallBack();
       
   157 		}
       
   158 	}
       
   159 
       
   160 /**
       
   161 Sends the response for the request MrcnptoAddToNowPlaying()
       
   162 
       
   163 The client must call NowPlayingContentChanged() if the content of the now 
       
   164 playing list has been changed after the client successfully adds the item
       
   165 to the now playing list and provides the response with KErrNone through 
       
   166 this function.
       
   167 
       
   168 param aErr The result of add to now playing operation.
       
   169     - KErrNone if the operation was successful.
       
   170     - KErrInvalidMediaLibraryStateCookie if the client is able to maintain 
       
   171       unique UIDs accross the entire virtual filesystem, but the media 
       
   172       library state cookie provided does not match the client's state cookie.
       
   173     - KErrInvalidUid if the uid of the item provided does not 
       
   174       refer to any valid item.
       
   175     - KErrNowPlayingUidIsADirectory if the uid of the item provided refers to
       
   176       a directory which can not be handled by this media player.
       
   177     - KErrNowPlayingMediaInUse if the item is in use and can not be added to 
       
   178       now playing list.
       
   179     - KErrNowPlayingListFull if the now playing list if full and no more items
       
   180       can be added.
       
   181     - System wide error code otherwise.
       
   182 
       
   183 @see NowPlayingContentChanged()
       
   184 */
       
   185 EXPORT_C void CRemConNowPlayingTargetBase::AddToNowPlayingResponse(TInt aErr)
       
   186 	{
       
   187 	TUint8 status = RAvrcpIPC::SymbianErrToStatus(aErr);
       
   188 	SendResponse(status, EAddToNowPlaying);
       
   189 
       
   190 	iInProgress = EFalse;		
       
   191 	if (!iMsgQueue->IsEmpty())
       
   192 		{
       
   193 		iNextMessageCallBack->CallBack();
       
   194 		}
       
   195 	}
       
   196 
       
   197 /**
       
   198 Called by the client in the case that the now playing content changed.
       
   199 
       
   200 @see PlayItemResponse()
       
   201 @see AddToNowPlayingResponse()
       
   202 */
       
   203 EXPORT_C void CRemConNowPlayingTargetBase::NowPlayingContentChanged()
       
   204 	{
       
   205 	if(iNotificationPending)
       
   206 		{
       
   207 		iNotificationPending = EFalse;
       
   208 		SendNotificationResponse(ERemConNotifyResponseChanged);
       
   209 		}
       
   210 	}
       
   211 
       
   212 void CRemConNowPlayingTargetBase::SendResponse(TUint8 aStatus, TUint aOperationId)
       
   213 	{
       
   214 	TInt error = KErrNone;
       
   215 
       
   216 	// Formats the response in a RRemConNowPlayingResponse
       
   217 	RRemConNowPlayingResponse response;
       
   218 	response.iStatus = aStatus;
       
   219 	
       
   220 	TRAP(error, response.WriteL(iOutBuf));
       
   221 	if (error == KErrNone)
       
   222 		{
       
   223 		// Send the response back to the CT
       
   224 		error = InterfaceSelector().SendUnreliable(
       
   225 				TUid::Uid(KRemConNowPlayingApiUid),
       
   226 				aOperationId, ERemConResponse, iOutBuf );
       
   227 		}
       
   228 
       
   229 	}
       
   230 
       
   231 void CRemConNowPlayingTargetBase::SendError(TInt aError, TUint aOperationId)
       
   232 	{
       
   233 	TInt error = KErrNone;	
       
   234 	RAvrcpIPCError response;
       
   235 	response.iError = RAvrcpIPC::SymbianErrorCheck(aError);
       
   236 	TRAP(error, response.WriteL(iOutBuf));
       
   237 	if (error == KErrNone)
       
   238 		{
       
   239 		InterfaceSelector().SendUnreliable(TUid::Uid(KRemConNowPlayingApiUid),
       
   240 				aOperationId, ERemConResponse, iOutBuf);
       
   241 		}
       
   242 	}
       
   243 
       
   244 // From MRemConInterfaceIf2
       
   245 void CRemConNowPlayingTargetBase::MrcibNewMessage(
       
   246 		TUint aOperationId, 
       
   247 		const TDesC8& aData, 
       
   248 		TRemConMessageSubType aMsgSubType)
       
   249 	{
       
   250 	LOG_FUNC
       
   251 	LOG2(KLogFormat, aOperationId, aData.Length());
       
   252 
       
   253 	TMetadataTransferPDU currentOp =
       
   254 	RAvrcpIPC::GetPDUIdFromIPCOperationId(aOperationId);
       
   255 	switch(currentOp)
       
   256 		{
       
   257 	case EPlayItem:
       
   258 		if ( !iInProgress && 
       
   259 			 !iMsgQueue->Find(TUid::Uid(KRemConNowPlayingApiUid), EPlayItem))
       
   260 			{
       
   261 			ProcessPlayItem(aData);
       
   262 			}
       
   263 		else
       
   264 			{
       
   265 			AddToOperationQueue(EPlayItem, aData);
       
   266 			}
       
   267 		break;
       
   268 	case EAddToNowPlaying:
       
   269 		if ( !iInProgress && 
       
   270 			 !iMsgQueue->Find(TUid::Uid(KRemConNowPlayingApiUid), EAddToNowPlaying))
       
   271 			{
       
   272 			ProcessAddToNowPlaying(aData);
       
   273 			}
       
   274 		else
       
   275 			{
       
   276 			AddToOperationQueue(EAddToNowPlaying, aData);
       
   277 			}
       
   278 		break;
       
   279 	case ERegisterNotification:
       
   280 		{
       
   281 		// obtain eventId from aOperationId
       
   282 		TRegisterNotificationEvent eventId = 
       
   283 		RAvrcpIPC::GetEventIdFromIPCOperationId(aOperationId);
       
   284 		
       
   285 		// If asserted here, must something wrong occured in the 
       
   286 		// remconbearer handling
       
   287 		__ASSERT_DEBUG(eventId == ERegisterNotificationNowPlayingContentChanged
       
   288 				, NowPlayingFault::Fault(EInvalidEventId));
       
   289         
       
   290 		// register for Notifications
       
   291 		if (aMsgSubType == ERemConNotifyCommandAwaitingInterim)
       
   292 			{
       
   293 			ProcessGetStatusAndBeginObserving();
       
   294 			}
       
   295 		else if (aMsgSubType == ERemConNotifyCommandAwaitingChanged)
       
   296 			{
       
   297 			ProcessGetStatus();
       
   298 			}
       
   299 	 	break;
       
   300 		}
       
   301 	default:
       
   302 		break;
       
   303 		};
       
   304 	}
       
   305 	
       
   306 void CRemConNowPlayingTargetBase::ProcessPlayItem(const TDesC8& aData)
       
   307 	{
       
   308 	TUint64 item;
       
   309 	TRemConFolderScope scope;
       
   310 	TUint16 uidCounter;
       
   311 	
       
   312 	if (!ProcessNowPlaying(aData, EPlayItem, item, scope, uidCounter))
       
   313 		{
       
   314 		return;
       
   315 		}
       
   316 	
       
   317 	iInProgress = ETrue;
       
   318 	if (iDaObserver && (uidCounter > 0))	
       
   319 		{
       
   320 		iDaObserver->MrcdanptoPlayItem(item, scope, uidCounter);
       
   321 		}
       
   322 	else if (!iDaObserver && (0 == uidCounter))
       
   323 		{
       
   324 		iDuObserver->MrcdunptoPlayItem(item, scope);
       
   325 		}
       
   326 	else
       
   327 		{
       
   328 		PlayItemResponse(KErrAvrcpAirInvalidParameter);
       
   329 		}
       
   330 	}
       
   331 
       
   332 void CRemConNowPlayingTargetBase::ProcessAddToNowPlaying(const TDesC8& aData)
       
   333 	{
       
   334 	TUint64 item;
       
   335 	TRemConFolderScope scope;
       
   336 	TUint16 uidCounter;
       
   337 	
       
   338 	if (!ProcessNowPlaying(aData, EAddToNowPlaying, item, scope, uidCounter))
       
   339 		{
       
   340 		return;
       
   341 		}
       
   342 
       
   343 	iInProgress = ETrue;
       
   344 	if (iDaObserver && (uidCounter > 0))
       
   345 		{
       
   346 		iDaObserver->MrcdanptoAddToNowPlaying(item, scope, uidCounter);
       
   347 		}
       
   348 	else if (!iDaObserver && (0 == uidCounter))
       
   349 		{
       
   350 		iDuObserver->MrcdunptoAddToNowPlaying(item, scope);
       
   351 		}
       
   352 	else
       
   353 		{
       
   354 		AddToNowPlayingResponse(KErrAvrcpAirInvalidParameter);
       
   355 		}
       
   356 	}
       
   357 
       
   358 TBool CRemConNowPlayingTargetBase::ProcessNowPlaying(
       
   359 		const TDesC8& aData, 
       
   360 		TUint aOperationId,
       
   361 		TUint64& aItem, 
       
   362 		TRemConFolderScope& aScope, 
       
   363 		TUint16& aMediaLibraryStateCookie)
       
   364 	{
       
   365 	RRemConNowPlayingRequest request;
       
   366 	TRAPD(error, request.ReadL(aData))
       
   367 	if (error != KErrNone)
       
   368 		{
       
   369 		// Nothing in packet
       
   370 		SendError(KErrAvrcpMetadataParameterNotFound, aOperationId);
       
   371 		return EFalse;
       
   372 		}
       
   373     
       
   374 	aItem = request.iElement;
       
   375 	aScope = request.iScope;
       
   376 	aMediaLibraryStateCookie = request.iUidCounter;
       
   377 	
       
   378 	//Does not allow invalid scope
       
   379 	if (   aScope != EBrowseFolder 
       
   380 		&& aScope != ESearchResultFolder
       
   381 		&& aScope != ENowPlayingFolder )
       
   382 		{
       
   383 		SendError(KErrAvrcpAirInvalidScope, aOperationId);
       
   384 		return EFalse;
       
   385 		}
       
   386 	return ETrue;
       
   387 	}
       
   388 
       
   389 void CRemConNowPlayingTargetBase::ProcessGetStatusAndBeginObserving()
       
   390 	{
       
   391 	// and request another notification (if there is not one already pending)
       
   392 	// on the next state change  
       
   393 	iNotificationPending = ETrue;
       
   394 		
       
   395 	// send the current status
       
   396 	SendNotificationResponse(ERemConNotifyResponseInterim);
       
   397 	}
       
   398 
       
   399 void CRemConNowPlayingTargetBase::ProcessGetStatus()
       
   400 	{
       
   401 	// send the current value
       
   402 	SendNotificationResponse(ERemConNotifyResponseChanged);
       
   403 	}
       
   404 
       
   405 void CRemConNowPlayingTargetBase::SendNotificationResponse(
       
   406 		TRemConMessageSubType aMsgSubType)
       
   407 	{
       
   408 	LOG_FUNC
       
   409 
       
   410 	TInt error = KErrNone;
       
   411 
       
   412 	// No extra data needed
       
   413 	RAvrcpIPCError response;
       
   414 	response.iError = KErrNone;
       
   415 	TRAP(error, response.WriteL(iOutBuf));
       
   416 
       
   417 	if (error == KErrNone)
       
   418 		{
       
   419 		// send the response back to the CT
       
   420 		TUint operationId = 
       
   421 		RAvrcpIPC::SetIPCOperationIdFromEventId(
       
   422 				ERegisterNotificationNowPlayingContentChanged);
       
   423 		
       
   424 		error = InterfaceSelector().SendUnreliable(
       
   425 				TUid::Uid(KRemConNowPlayingApiUid),
       
   426 				operationId, ERemConResponse, aMsgSubType, iOutBuf);
       
   427 		}
       
   428 	}
       
   429 
       
   430 TInt CRemConNowPlayingTargetBase::NextMessageCb(TAny* aThis)
       
   431 	{
       
   432 	static_cast<CRemConNowPlayingTargetBase*>(aThis)->DoNextMessage();
       
   433 	return KErrNone;
       
   434 	}
       
   435 
       
   436 void CRemConNowPlayingTargetBase::DoNextMessage()
       
   437 	{
       
   438 	CRemConQueuedMessage* msg = iMsgQueue->First();
       
   439 	iMsgQueue->Remove(*msg);
       
   440 	
       
   441 	switch (msg->iOperationId)
       
   442 		{
       
   443 		case EPlayItem:
       
   444 			ProcessPlayItem(msg->Data());
       
   445 			break;
       
   446 		case EAddToNowPlaying:
       
   447 			ProcessAddToNowPlaying(msg->Data());
       
   448 			break;
       
   449 		default:
       
   450 			// Never come here.
       
   451 			ASSERT(NULL);
       
   452 			break;
       
   453 		}
       
   454 	delete msg;
       
   455 	}
       
   456 
       
   457 void CRemConNowPlayingTargetBase::AddToOperationQueue(TInt aOperationId, 
       
   458 		const TDesC8& aData)
       
   459 	{
       
   460 	CRemConQueuedMessage* msg = NULL;
       
   461 	TRAPD(err, msg = CRemConQueuedMessage::NewL(
       
   462 			TUid::Uid(KRemConNowPlayingApiUid), aData, aOperationId));			
       
   463 	if (err == KErrNone)
       
   464 		{
       
   465 		iMsgQueue->AddLast(*msg);
       
   466 		}
       
   467 	else
       
   468 		{
       
   469 		SendError(KErrAvrcpMetadataInternalError, aOperationId);
       
   470 		}
       
   471 	}
       
   472