bluetoothappprofiles/avrcp/playerinformation/src/playerevents.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 // This file contains the events part of the PlayerInformation API.
       
    15 // 
       
    16 //
       
    17 
       
    18 /**
       
    19  @file
       
    20  @publishedAll
       
    21  @released
       
    22 */
       
    23 
       
    24 #include <bluetooth/logger.h>
       
    25 #include <remconinterfaceselector.h>
       
    26 #include <remconbeareravrcp.h>
       
    27 #include <playerinformationtarget.h>
       
    28 #include <playerinformationtargetobserver.h>
       
    29 
       
    30 #include "playerapplicationsetting.h"
       
    31 #include "eventsmask.h"
       
    32 #include "playereventsutils.h"
       
    33 #include "playerinformation.h"
       
    34 
       
    35 #ifdef __FLOG_ACTIVE
       
    36 _LIT8(KLogComponent, LOG_COMPONENT_AVRCP_PLAYER_INFO);
       
    37 #endif
       
    38 
       
    39 EXPORT_C void MPlayerEventsObserver::PlaybackStatusChanged(TPlaybackStatus aStatus)
       
    40 	{
       
    41 	DoPlaybackStatusChanged(aStatus);
       
    42 	}
       
    43 
       
    44 EXPORT_C void MPlayerEventsObserver::TrackChanged(TUint64 aTrackId, TUint32 aLengthInMilliseconds) 
       
    45 	{
       
    46 	DoTrackChanged(aTrackId, aLengthInMilliseconds); 
       
    47 	}
       
    48 
       
    49 EXPORT_C void MPlayerEventsObserver::TrackReachedEnd() 
       
    50 	{
       
    51 	DoTrackReachedEnd();
       
    52 	}
       
    53 
       
    54 EXPORT_C void MPlayerEventsObserver::TrackReachedStart()
       
    55 	{
       
    56 	DoTrackReachedStart();
       
    57 	}
       
    58 
       
    59 EXPORT_C void MPlayerEventsObserver::SetPlaybackPosition(TUint32 aMilliseconds) 
       
    60 	{
       
    61 	DoSetPlaybackPosition(aMilliseconds); 
       
    62 	}
       
    63 	
       
    64 EXPORT_C void MPlayerEventsObserver::SetBatteryStatus(TTargetBatteryStatus aBatteryStatus) 
       
    65 	{
       
    66 	DoSetBatteryStatus(aBatteryStatus); 
       
    67 	}
       
    68 
       
    69 void CPlayerInfoTarget::ProcessGetStatusAndBeginObserving( const TUint aOperationId, TRegisterNotificationEvent aEventId, const TDesC8& aData)
       
    70 	{
       
    71 	// check the event is in the supported list
       
    72 	if (!iSupportedNotificationEventList->Find(aEventId))
       
    73 		{
       
    74 		// Not supported so return error
       
    75 		SendError(KErrAvrcpMetadataInvalidParameter, aOperationId, ERemConNotifyResponseInterim);
       
    76 		return;
       
    77 		}
       
    78 		
       
    79 	// if the event is EPlaybackPosChanged then the timeinterval is included in the RegisterNofication
       
    80 	if (aEventId == ERegisterNotificationPlaybackPosChanged)
       
    81 		{
       
    82 		// decode the playback interval from aData
       
    83 		TInt error = 0;
       
    84 		RRemConPlayerInformation32BitResponse request;
       
    85 		TRAP(error, request.ReadL(aData));
       
    86 		
       
    87 		if (error != KErrNone)
       
    88 			{
       
    89 			// Not supported so return error
       
    90 			SendError(KErrAvrcpMetadataParameterNotFound, aOperationId, ERemConNotifyResponseInterim);
       
    91 			return;
       
    92 			}
       
    93 		
       
    94 		// save the playback interval
       
    95 		iPlayBackIntervalInMilliseconds = request.iValue * 1000;
       
    96 		
       
    97 		// and the current position
       
    98 		iLastNotifiedPlaybackPositionInMilliseconds = iPlaybackPositionInMilliseconds;
       
    99 		}
       
   100 		
       
   101 	// and request another notification (if there is not one already pending)
       
   102 	// on the next state change  
       
   103 	if (KErrNotFound ==iPendingNotificationEventList.Find(aEventId))
       
   104 		{
       
   105 		if (iPendingNotificationEventList.Append(aEventId) != KErrNone)
       
   106 			{
       
   107 			return SendError(KErrAvrcpMetadataInternalError, aOperationId);   // Try to send internal error if OOM
       
   108 			}
       
   109 		}
       
   110 		
       
   111 	// send the current status
       
   112 	SendNotificationResponse(aEventId, ERemConNotifyResponseInterim );
       
   113 	}
       
   114 
       
   115 void CPlayerInfoTarget::ProcessGetStatus( const TUint aOperationId, TRegisterNotificationEvent aEventId)
       
   116 	{
       
   117 	// send the current value
       
   118 	if (iSupportedNotificationEventList->Find(aEventId))
       
   119 		{
       
   120 		SendNotificationResponse(aEventId, ERemConNotifyResponseChanged );
       
   121 		}
       
   122 	else
       
   123 		{
       
   124 		// Not found so return error
       
   125 		SendError(KErrAvrcpMetadataInvalidParameter, aOperationId, ERemConNotifyResponseChanged);
       
   126 		}
       
   127 	}
       
   128 		
       
   129 /* ProcessGetPlayStatus This returns the current values of SongLength, 
       
   130    SongPosition and PlayStatus.
       
   131    Note if SongLength and SongPosition are not supported KPlaybackPositionUnknown is returned
       
   132  */
       
   133 void CPlayerInfoTarget::ProcessGetPlayStatus()
       
   134 	{
       
   135 	LOG_FUNC
       
   136 
       
   137 	TInt error =0;
       
   138 
       
   139 	// format the response in a RRemConPlayerInformationGetPlayStatusResponse
       
   140 	RRemConPlayerInformationGetPlayStatusResponse response;
       
   141 	response.iTrackLength = iLengthInMilliseconds;
       
   142 	response.iPlayPos = iPlaybackPositionInMilliseconds;
       
   143 	response.iStatus = iPlayBackStatus;
       
   144 	
       
   145 	TRAP(error, response.WriteL(iOutBuf));
       
   146 	if (error == KErrNone)
       
   147 		{
       
   148 		// send the response back to the CT
       
   149 		error = InterfaceSelector().SendUnreliable(TUid::Uid(KRemConPlayerInformationUid),
       
   150 												EGetPlayStatus, ERemConResponse, iOutBuf );
       
   151 		}
       
   152 	}
       
   153 
       
   154 /* ProcessGetPlayStatusUpdate returns the current play status if it has changed
       
   155  * relative to the provided play status, otherwise the request is queued until
       
   156  * the play status changes.
       
   157  */
       
   158 void CPlayerInfoTarget::ProcessGetPlayStatusUpdate(const TDesC8& aData)
       
   159 	{
       
   160 	LOG_FUNC
       
   161 
       
   162 	// Bearer should never send us more than one of these in parallel
       
   163 	__ASSERT_DEBUG(!iPlaybackStatusUpdatePending, PlayerEventsUtils::Panic(ETwoGetPlayStatusUpdatesQueued));
       
   164 	
       
   165 	TInt error =0;
       
   166 	RRemConPlayerInformationGetPlayStatusUpdateRequest request;
       
   167 	TRAP(error, request.ReadL(aData));
       
   168 	__ASSERT_DEBUG(error == KErrNone, PlayerEventsUtils::Panic(EBadlyFormattedInternalData));
       
   169 
       
   170 	if(request.iStatus != iPlayBackStatus)
       
   171 		{
       
   172 		// format the response in a RRemConPlayerInformationGetPlayStatusResponse
       
   173 		RRemConPlayerInformationGetPlayStatusUpdateResponse response;
       
   174 		response.iStatus = iPlayBackStatus;
       
   175 		
       
   176 		TRAP(error, response.WriteL(iOutBuf));
       
   177 		if (error == KErrNone)
       
   178 			{
       
   179 			// send the response back to the CT
       
   180 			error = InterfaceSelector().SendUnreliable(TUid::Uid(KRemConPlayerInformationUid),
       
   181 													EGetPlayStatusUpdate, ERemConResponse, iOutBuf );
       
   182 			if(error != KErrNone)
       
   183 				{
       
   184 				// We will try and send the response again next time we get an update
       
   185 				iPlaybackStatusUpdatePending = ETrue;
       
   186 				}
       
   187 			}
       
   188 		}
       
   189 	else
       
   190 		{
       
   191 		iPlaybackStatusUpdatePending = ETrue;
       
   192 		}
       
   193 	}
       
   194 
       
   195 // Send a Notification message for aEventID 
       
   196 void CPlayerInfoTarget::SendNotificationResponse( TRegisterNotificationEvent aEventId, TRemConMessageSubType aMsgSubType )
       
   197 	{
       
   198 	LOG_FUNC
       
   199 
       
   200 	TInt error = 0;
       
   201 	iOutBuf.Zero();
       
   202 
       
   203 	if (!iSupportedNotificationEventList->Find(aEventId))
       
   204 		{
       
   205 		return SendError(KErrAvrcpMetadataInvalidParameter, 
       
   206 						 RAvrcpIPC::SetIPCOperationIdFromEventId(aEventId), aMsgSubType);
       
   207 		}
       
   208 		
       
   209 	switch (aEventId)
       
   210 		{
       
   211 		case ERegisterNotificationTrackReachedEnd:
       
   212 		case ERegisterNotificationTrackReachedStart:
       
   213 			{
       
   214 			// no extra data for reached start or end 
       
   215 			RAvrcpIPCError response;
       
   216 			response.iError = KErrNone;
       
   217 			TRAP(error, response.WriteL(iOutBuf));
       
   218 			break;
       
   219 			}
       
   220 
       
   221 		case ERegisterNotificationPlaybackStatusChanged:
       
   222 			{
       
   223 			// 8bit response -- current playback status 
       
   224 			RRemConPlayerInformation8BitResponse response;
       
   225 			response.iValue = iPlayBackStatus;
       
   226 			TRAP(error, response.WriteL(iOutBuf));
       
   227 			break;
       
   228 			}
       
   229 
       
   230 		case ERegisterNotificationBatteryStatusChanged:
       
   231 			{
       
   232 			// 8bit response -- current battery status
       
   233 			RRemConPlayerInformation8BitResponse response;
       
   234 			response.iValue = iBatteryStatus;
       
   235 			TRAP(error, response.WriteL(iOutBuf));
       
   236 			break;
       
   237 			}
       
   238 
       
   239 		case ERegisterNotificationPlaybackPosChanged:
       
   240 			{
       
   241 			// 32bit response -- current playback position in millisecond 
       
   242 			RRemConPlayerInformation32BitResponse response;
       
   243 			response.iValue = iPlaybackPositionInMilliseconds;
       
   244 			TRAP(error, response.WriteL(iOutBuf));
       
   245 			break;
       
   246 			}
       
   247 
       
   248 		case ERegisterNotificationTrackChanged:
       
   249 			{
       
   250 			// 64bit response -- index of the current track 
       
   251 			RRemConPlayerInformation64BitResponse response;
       
   252 			response.iValue = iTrackId;
       
   253 			TRAP(error, response.WriteL(iOutBuf));
       
   254 			break;
       
   255 			}
       
   256 
       
   257 		case ERegisterNotificationPlayerApplicationSettingChanged:
       
   258 			{
       
   259 			// Send a list of the settings that have changed followed by their value 
       
   260 			// starting with the number of attributes to be sent 
       
   261 			RRemConPlayerAttributeIdsAndValues response;
       
   262 			response.iNumberAttributes = 0;
       
   263 		
       
   264 			// for every entry in the list
       
   265 			THashMapIter<TInt, CPlayerApplicationSettings*> iter(iPlayerApplicationSettings);
       
   266 			CPlayerApplicationSettings* const* setting = iter.NextValue();
       
   267 			while ( setting != NULL )
       
   268 				{
       
   269 				TUint8 value = (*setting)->GetCurrentValue();
       
   270 				TInt ret1 = response.iAttributeValue.Append(value);
       
   271 				TInt ret2 = response.iAttributeId.Append((*setting)->GetAttributeID());
       
   272 				if (ret1 != KErrNone || ret2 != KErrNone)
       
   273 					{
       
   274 					response.Close();
       
   275 					return SendError(KErrAvrcpMetadataInternalError, 
       
   276 									 RAvrcpIPC::SetIPCOperationIdFromEventId(aEventId),
       
   277 									 aMsgSubType);   // Try to send internal error if OOM
       
   278 					}
       
   279 				response.iNumberAttributes++;
       
   280 				setting = iter.NextValue();
       
   281 				}
       
   282 				
       
   283 			TRAP(error, response.WriteL(iOutBuf));
       
   284 			response.Close();
       
   285 			break;
       
   286 			}
       
   287 		default:
       
   288 			return;
       
   289 		}
       
   290 	
       
   291 	if (error == KErrNone)
       
   292 		{
       
   293 		// send the response back to the CT
       
   294 		TUint operationId = RAvrcpIPC::SetIPCOperationIdFromEventId(aEventId);
       
   295 		error = InterfaceSelector().SendUnreliable(TUid::Uid(KRemConPlayerInformationUid),
       
   296 												operationId, ERemConResponse, aMsgSubType, iOutBuf);
       
   297 		}
       
   298 	}
       
   299 	 
       
   300 // from MPlayerEventsObserver
       
   301  void CPlayerInfoTarget::DoPlaybackStatusChanged(TPlaybackStatus  aStatus)
       
   302 	{
       
   303 	LOG_FUNC
       
   304 
       
   305 	iPlayBackStatus = aStatus;
       
   306 	
       
   307 	// if the playback status is in the current event list
       
   308 	TInt pos = iPendingNotificationEventList.Find( ERegisterNotificationPlaybackStatusChanged );
       
   309 	if (pos != KErrNotFound)
       
   310 		{
       
   311 		iPendingNotificationEventList.Remove( pos );
       
   312 		SendNotificationResponse( ERegisterNotificationPlaybackStatusChanged, ERemConNotifyResponseChanged);
       
   313 		}
       
   314 	
       
   315 	pos = iPendingNotificationEventList.Find( ERegisterNotificationPlaybackPosChanged );
       
   316 	if (pos != KErrNotFound)
       
   317 		{
       
   318 		iPendingNotificationEventList.Remove( pos );
       
   319 		SendNotificationResponse(ERegisterNotificationPlaybackPosChanged, ERemConNotifyResponseChanged);
       
   320 		}
       
   321 	
       
   322 	if(iPlaybackStatusUpdatePending)
       
   323 		{
       
   324 		// format the response in a RRemConPlayerInformationGetPlayStatusResponse
       
   325 		RRemConPlayerInformationGetPlayStatusUpdateResponse response;
       
   326 		response.iStatus = iPlayBackStatus;
       
   327 		
       
   328 		TRAPD(error, response.WriteL(iOutBuf));
       
   329 		if (error == KErrNone)
       
   330 			{
       
   331 			// send the response back to the CT
       
   332 			error = InterfaceSelector().SendUnreliable(TUid::Uid(KRemConPlayerInformationUid),
       
   333 													EGetPlayStatusUpdate, ERemConResponse, iOutBuf );
       
   334 			if(error == KErrNone)
       
   335 				{
       
   336 				iPlaybackStatusUpdatePending = EFalse;
       
   337 				}
       
   338 			// if we did error we will try and respond again next time the client's play status
       
   339 			// changes
       
   340 			}
       
   341 		}
       
   342 	}
       
   343 	
       
   344 void CPlayerInfoTarget::DoTrackChanged(TUint64 aTrackId, TUint32 aLengthInMilliseconds)
       
   345 	{
       
   346 	LOG_FUNC
       
   347 
       
   348 	iTrackId = aTrackId;
       
   349 	iLengthInMilliseconds = aLengthInMilliseconds;
       
   350 
       
   351 	// if the playback status is in the current event list 
       
   352 	TInt pos = iPendingNotificationEventList.Find( ERegisterNotificationTrackChanged );
       
   353 	if (pos != KErrNotFound)
       
   354 		{
       
   355 		iPendingNotificationEventList.Remove( pos );
       
   356 		SendNotificationResponse(ERegisterNotificationTrackChanged, ERemConNotifyResponseChanged);
       
   357 		}
       
   358 
       
   359 	pos = iPendingNotificationEventList.Find( ERegisterNotificationPlaybackPosChanged );
       
   360 	if (pos != KErrNotFound)
       
   361 		{
       
   362 		iPendingNotificationEventList.Remove( pos );
       
   363 		iPlaybackPositionInMilliseconds = 0;	//set 0 to current position for new track
       
   364 		SendNotificationResponse(ERegisterNotificationPlaybackPosChanged, ERemConNotifyResponseChanged);
       
   365 		}
       
   366 	}
       
   367 
       
   368 void CPlayerInfoTarget::DoTrackReachedEnd()
       
   369 	{
       
   370 	LOG_FUNC
       
   371 	
       
   372 	iTrackPosition = EEnd;
       
   373 
       
   374 	// if the ETrackReachedEnd status is in the current event list 
       
   375 	TInt pos = iPendingNotificationEventList.Find( ERegisterNotificationTrackReachedEnd );
       
   376 	if (pos != KErrNotFound)
       
   377 		{
       
   378 		iPendingNotificationEventList.Remove( pos );
       
   379 		SendNotificationResponse(ERegisterNotificationTrackReachedEnd, ERemConNotifyResponseChanged);
       
   380 		}
       
   381 	
       
   382 	pos = iPendingNotificationEventList.Find( ERegisterNotificationPlaybackPosChanged );
       
   383 	if (pos != KErrNotFound)
       
   384 		{
       
   385 		iPendingNotificationEventList.Remove( pos );
       
   386 		iPlaybackPositionInMilliseconds = iLengthInMilliseconds;
       
   387 		SendNotificationResponse(ERegisterNotificationPlaybackPosChanged, ERemConNotifyResponseChanged);
       
   388 		}
       
   389 	}
       
   390 
       
   391 void CPlayerInfoTarget::DoTrackReachedStart()
       
   392 	{
       
   393 	LOG_FUNC
       
   394 
       
   395 	iTrackPosition = EStart;
       
   396 
       
   397 	// if the ETrackReachedStart status is in the current event list 
       
   398 	TInt pos = iPendingNotificationEventList.Find( ERegisterNotificationTrackReachedStart );
       
   399 	if (pos != KErrNotFound)
       
   400 		{
       
   401 		iPendingNotificationEventList.Remove( pos );
       
   402 		SendNotificationResponse(ERegisterNotificationTrackReachedStart, ERemConNotifyResponseChanged);
       
   403 		}
       
   404 	
       
   405 	pos = iPendingNotificationEventList.Find( ERegisterNotificationPlaybackPosChanged );
       
   406 	if (pos != KErrNotFound)
       
   407 		{
       
   408 		iPendingNotificationEventList.Remove( pos );
       
   409 		iPlaybackPositionInMilliseconds = 0;
       
   410 		SendNotificationResponse(ERegisterNotificationPlaybackPosChanged, ERemConNotifyResponseChanged);
       
   411 		}
       
   412 	}
       
   413 
       
   414 void CPlayerInfoTarget::DoSetPlaybackPosition(TUint32 aMilliseconds)		
       
   415 	{
       
   416 	LOG_FUNC
       
   417 	
       
   418 	iPlaybackPositionInMilliseconds = aMilliseconds;
       
   419 
       
   420 	// if the playback position is in the current Notification event list 
       
   421 	TInt pos = iPendingNotificationEventList.Find( ERegisterNotificationPlaybackPosChanged );
       
   422 	if (pos != KErrNotFound)
       
   423 		{
       
   424 		// a notification has been requested, now check if it is due
       
   425 
       
   426 		TUint32 difference = (iPlaybackPositionInMilliseconds > iLastNotifiedPlaybackPositionInMilliseconds) ?
       
   427         	iPlaybackPositionInMilliseconds - iLastNotifiedPlaybackPositionInMilliseconds:
       
   428         	iLastNotifiedPlaybackPositionInMilliseconds - iPlaybackPositionInMilliseconds;
       
   429 
       
   430 		if (difference >= iPlayBackIntervalInMilliseconds)
       
   431 			{
       
   432 			// Due now so send
       
   433 			iPendingNotificationEventList.Remove( pos );
       
   434 			SendNotificationResponse(ERegisterNotificationPlaybackPosChanged, ERemConNotifyResponseChanged);			
       
   435 			}	
       
   436 		}
       
   437 	}
       
   438 
       
   439 void CPlayerInfoTarget::DoSetBatteryStatus(TTargetBatteryStatus aBatteryStatus)
       
   440 	{
       
   441 	LOG_FUNC
       
   442 
       
   443 	TBool validStatus = ETrue;
       
   444 	if (aBatteryStatus < MPlayerEventsObserver::ENormal || 
       
   445 		aBatteryStatus > MPlayerEventsObserver::EFullCharge)
       
   446 		{
       
   447 		LOG1(_L("Invalid battery status: %d"),aBatteryStatus);
       
   448 		validStatus = EFalse;
       
   449 		}
       
   450 	else
       
   451 		{
       
   452 		iBatteryStatus = aBatteryStatus;
       
   453 		}
       
   454 
       
   455 	// if the battery status is in the current event list
       
   456 	TInt pos = iPendingNotificationEventList.Find( ERegisterNotificationBatteryStatusChanged );
       
   457 	if (pos != KErrNotFound)
       
   458 		{
       
   459 		iPendingNotificationEventList.Remove( pos );
       
   460 		if (validStatus)
       
   461 			{
       
   462 			SendNotificationResponse(ERegisterNotificationBatteryStatusChanged, ERemConNotifyResponseChanged);
       
   463 			}
       
   464 		}
       
   465 	}
       
   466 	
       
   467 void CPlayerInfoTarget::SendError(TInt aError, TInt aOperationId, TRemConMessageSubType aSubType)
       
   468 	{
       
   469 	TInt error = 0;
       
   470 	RAvrcpIPCError response;
       
   471 	response.iError = aError;
       
   472 	TRAP(error, response.WriteL(iOutBuf));   // Don't send error if OOM
       
   473 	if (error == KErrNone)
       
   474 		InterfaceSelector().SendUnreliable(TUid::Uid(KRemConPlayerInformationUid),
       
   475 										aOperationId, ERemConResponse, aSubType, iOutBuf);
       
   476 	}
       
   477