diff -r 22de2e391156 -r 20ac952a623c remotecontrol/avrcp/playerinformation/src/playerevents.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/remotecontrol/avrcp/playerinformation/src/playerevents.cpp Wed Oct 13 16:20:29 2010 +0300 @@ -0,0 +1,477 @@ +// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// This file contains the events part of the PlayerInformation API. +// +// + +/** + @file + @publishedAll + @released +*/ + +#include +#include +#include +#include +#include + +#include "playerapplicationsetting.h" +#include "eventsmask.h" +#include "playereventsutils.h" +#include "playerinformation.h" + +#ifdef __FLOG_ACTIVE +_LIT8(KLogComponent, LOG_COMPONENT_AVRCP_PLAYER_INFO); +#endif + +EXPORT_C void MPlayerEventsObserver::PlaybackStatusChanged(TPlaybackStatus aStatus) + { + DoPlaybackStatusChanged(aStatus); + } + +EXPORT_C void MPlayerEventsObserver::TrackChanged(TUint64 aTrackId, TUint32 aLengthInMilliseconds) + { + DoTrackChanged(aTrackId, aLengthInMilliseconds); + } + +EXPORT_C void MPlayerEventsObserver::TrackReachedEnd() + { + DoTrackReachedEnd(); + } + +EXPORT_C void MPlayerEventsObserver::TrackReachedStart() + { + DoTrackReachedStart(); + } + +EXPORT_C void MPlayerEventsObserver::SetPlaybackPosition(TUint32 aMilliseconds) + { + DoSetPlaybackPosition(aMilliseconds); + } + +EXPORT_C void MPlayerEventsObserver::SetBatteryStatus(TTargetBatteryStatus aBatteryStatus) + { + DoSetBatteryStatus(aBatteryStatus); + } + +void CPlayerInfoTarget::ProcessGetStatusAndBeginObserving( const TUint aOperationId, TRegisterNotificationEvent aEventId, const TDesC8& aData) + { + // check the event is in the supported list + if (!iSupportedNotificationEventList->Find(aEventId)) + { + // Not supported so return error + SendError(KErrAvrcpMetadataInvalidParameter, aOperationId, ERemConNotifyResponseInterim); + return; + } + + // if the event is EPlaybackPosChanged then the timeinterval is included in the RegisterNofication + if (aEventId == ERegisterNotificationPlaybackPosChanged) + { + // decode the playback interval from aData + TInt error = 0; + RRemConPlayerInformation32BitResponse request; + TRAP(error, request.ReadL(aData)); + + if (error != KErrNone) + { + // Not supported so return error + SendError(KErrAvrcpMetadataParameterNotFound, aOperationId, ERemConNotifyResponseInterim); + return; + } + + // save the playback interval + iPlayBackIntervalInMilliseconds = request.iValue * 1000; + + // and the current position + iLastNotifiedPlaybackPositionInMilliseconds = iPlaybackPositionInMilliseconds; + } + + // and request another notification (if there is not one already pending) + // on the next state change + if (KErrNotFound ==iPendingNotificationEventList.Find(aEventId)) + { + if (iPendingNotificationEventList.Append(aEventId) != KErrNone) + { + return SendError(KErrAvrcpMetadataInternalError, aOperationId); // Try to send internal error if OOM + } + } + + // send the current status + SendNotificationResponse(aEventId, ERemConNotifyResponseInterim ); + } + +void CPlayerInfoTarget::ProcessGetStatus( const TUint aOperationId, TRegisterNotificationEvent aEventId) + { + // send the current value + if (iSupportedNotificationEventList->Find(aEventId)) + { + SendNotificationResponse(aEventId, ERemConNotifyResponseChanged ); + } + else + { + // Not found so return error + SendError(KErrAvrcpMetadataInvalidParameter, aOperationId, ERemConNotifyResponseChanged); + } + } + +/* ProcessGetPlayStatus This returns the current values of SongLength, + SongPosition and PlayStatus. + Note if SongLength and SongPosition are not supported KPlaybackPositionUnknown is returned + */ +void CPlayerInfoTarget::ProcessGetPlayStatus() + { + LOG_FUNC + + TInt error =0; + + // format the response in a RRemConPlayerInformationGetPlayStatusResponse + RRemConPlayerInformationGetPlayStatusResponse response; + response.iTrackLength = iLengthInMilliseconds; + response.iPlayPos = iPlaybackPositionInMilliseconds; + response.iStatus = iPlayBackStatus; + + TRAP(error, response.WriteL(iOutBuf)); + if (error == KErrNone) + { + // send the response back to the CT + error = InterfaceSelector().SendUnreliable(TUid::Uid(KRemConPlayerInformationUid), + EGetPlayStatus, ERemConResponse, iOutBuf ); + } + } + +/* ProcessGetPlayStatusUpdate returns the current play status if it has changed + * relative to the provided play status, otherwise the request is queued until + * the play status changes. + */ +void CPlayerInfoTarget::ProcessGetPlayStatusUpdate(const TDesC8& aData) + { + LOG_FUNC + + // Bearer should never send us more than one of these in parallel + __ASSERT_DEBUG(!iPlaybackStatusUpdatePending, PlayerEventsUtils::Panic(ETwoGetPlayStatusUpdatesQueued)); + + TInt error =0; + RRemConPlayerInformationGetPlayStatusUpdateRequest request; + TRAP(error, request.ReadL(aData)); + __ASSERT_DEBUG(error == KErrNone, PlayerEventsUtils::Panic(EBadlyFormattedInternalData)); + + if(request.iStatus != iPlayBackStatus) + { + // format the response in a RRemConPlayerInformationGetPlayStatusResponse + RRemConPlayerInformationGetPlayStatusUpdateResponse response; + response.iStatus = iPlayBackStatus; + + TRAP(error, response.WriteL(iOutBuf)); + if (error == KErrNone) + { + // send the response back to the CT + error = InterfaceSelector().SendUnreliable(TUid::Uid(KRemConPlayerInformationUid), + EGetPlayStatusUpdate, ERemConResponse, iOutBuf ); + if(error != KErrNone) + { + // We will try and send the response again next time we get an update + iPlaybackStatusUpdatePending = ETrue; + } + } + } + else + { + iPlaybackStatusUpdatePending = ETrue; + } + } + +// Send a Notification message for aEventID +void CPlayerInfoTarget::SendNotificationResponse( TRegisterNotificationEvent aEventId, TRemConMessageSubType aMsgSubType ) + { + LOG_FUNC + + TInt error = 0; + iOutBuf.Zero(); + + if (!iSupportedNotificationEventList->Find(aEventId)) + { + return SendError(KErrAvrcpMetadataInvalidParameter, + RAvrcpIPC::SetIPCOperationIdFromEventId(aEventId), aMsgSubType); + } + + switch (aEventId) + { + case ERegisterNotificationTrackReachedEnd: + case ERegisterNotificationTrackReachedStart: + { + // no extra data for reached start or end + RAvrcpIPCError response; + response.iError = KErrNone; + TRAP(error, response.WriteL(iOutBuf)); + break; + } + + case ERegisterNotificationPlaybackStatusChanged: + { + // 8bit response -- current playback status + RRemConPlayerInformation8BitResponse response; + response.iValue = iPlayBackStatus; + TRAP(error, response.WriteL(iOutBuf)); + break; + } + + case ERegisterNotificationBatteryStatusChanged: + { + // 8bit response -- current battery status + RRemConPlayerInformation8BitResponse response; + response.iValue = iBatteryStatus; + TRAP(error, response.WriteL(iOutBuf)); + break; + } + + case ERegisterNotificationPlaybackPosChanged: + { + // 32bit response -- current playback position in millisecond + RRemConPlayerInformation32BitResponse response; + response.iValue = iPlaybackPositionInMilliseconds; + TRAP(error, response.WriteL(iOutBuf)); + break; + } + + case ERegisterNotificationTrackChanged: + { + // 64bit response -- index of the current track + RRemConPlayerInformation64BitResponse response; + response.iValue = iTrackId; + TRAP(error, response.WriteL(iOutBuf)); + break; + } + + case ERegisterNotificationPlayerApplicationSettingChanged: + { + // Send a list of the settings that have changed followed by their value + // starting with the number of attributes to be sent + RRemConPlayerAttributeIdsAndValues response; + response.iNumberAttributes = 0; + + // for every entry in the list + THashMapIter iter(iPlayerApplicationSettings); + CPlayerApplicationSettings* const* setting = iter.NextValue(); + while ( setting != NULL ) + { + TUint8 value = (*setting)->GetCurrentValue(); + TInt ret1 = response.iAttributeValue.Append(value); + TInt ret2 = response.iAttributeId.Append((*setting)->GetAttributeID()); + if (ret1 != KErrNone || ret2 != KErrNone) + { + response.Close(); + return SendError(KErrAvrcpMetadataInternalError, + RAvrcpIPC::SetIPCOperationIdFromEventId(aEventId), + aMsgSubType); // Try to send internal error if OOM + } + response.iNumberAttributes++; + setting = iter.NextValue(); + } + + TRAP(error, response.WriteL(iOutBuf)); + response.Close(); + break; + } + default: + return; + } + + if (error == KErrNone) + { + // send the response back to the CT + TUint operationId = RAvrcpIPC::SetIPCOperationIdFromEventId(aEventId); + error = InterfaceSelector().SendUnreliable(TUid::Uid(KRemConPlayerInformationUid), + operationId, ERemConResponse, aMsgSubType, iOutBuf); + } + } + +// from MPlayerEventsObserver + void CPlayerInfoTarget::DoPlaybackStatusChanged(TPlaybackStatus aStatus) + { + LOG_FUNC + + iPlayBackStatus = aStatus; + + // if the playback status is in the current event list + TInt pos = iPendingNotificationEventList.Find( ERegisterNotificationPlaybackStatusChanged ); + if (pos != KErrNotFound) + { + iPendingNotificationEventList.Remove( pos ); + SendNotificationResponse( ERegisterNotificationPlaybackStatusChanged, ERemConNotifyResponseChanged); + } + + pos = iPendingNotificationEventList.Find( ERegisterNotificationPlaybackPosChanged ); + if (pos != KErrNotFound) + { + iPendingNotificationEventList.Remove( pos ); + SendNotificationResponse(ERegisterNotificationPlaybackPosChanged, ERemConNotifyResponseChanged); + } + + if(iPlaybackStatusUpdatePending) + { + // format the response in a RRemConPlayerInformationGetPlayStatusResponse + RRemConPlayerInformationGetPlayStatusUpdateResponse response; + response.iStatus = iPlayBackStatus; + + TRAPD(error, response.WriteL(iOutBuf)); + if (error == KErrNone) + { + // send the response back to the CT + error = InterfaceSelector().SendUnreliable(TUid::Uid(KRemConPlayerInformationUid), + EGetPlayStatusUpdate, ERemConResponse, iOutBuf ); + if(error == KErrNone) + { + iPlaybackStatusUpdatePending = EFalse; + } + // if we did error we will try and respond again next time the client's play status + // changes + } + } + } + +void CPlayerInfoTarget::DoTrackChanged(TUint64 aTrackId, TUint32 aLengthInMilliseconds) + { + LOG_FUNC + + iTrackId = aTrackId; + iLengthInMilliseconds = aLengthInMilliseconds; + + // if the playback status is in the current event list + TInt pos = iPendingNotificationEventList.Find( ERegisterNotificationTrackChanged ); + if (pos != KErrNotFound) + { + iPendingNotificationEventList.Remove( pos ); + SendNotificationResponse(ERegisterNotificationTrackChanged, ERemConNotifyResponseChanged); + } + + pos = iPendingNotificationEventList.Find( ERegisterNotificationPlaybackPosChanged ); + if (pos != KErrNotFound) + { + iPendingNotificationEventList.Remove( pos ); + iPlaybackPositionInMilliseconds = 0; //set 0 to current position for new track + SendNotificationResponse(ERegisterNotificationPlaybackPosChanged, ERemConNotifyResponseChanged); + } + } + +void CPlayerInfoTarget::DoTrackReachedEnd() + { + LOG_FUNC + + iTrackPosition = EEnd; + + // if the ETrackReachedEnd status is in the current event list + TInt pos = iPendingNotificationEventList.Find( ERegisterNotificationTrackReachedEnd ); + if (pos != KErrNotFound) + { + iPendingNotificationEventList.Remove( pos ); + SendNotificationResponse(ERegisterNotificationTrackReachedEnd, ERemConNotifyResponseChanged); + } + + pos = iPendingNotificationEventList.Find( ERegisterNotificationPlaybackPosChanged ); + if (pos != KErrNotFound) + { + iPendingNotificationEventList.Remove( pos ); + iPlaybackPositionInMilliseconds = iLengthInMilliseconds; + SendNotificationResponse(ERegisterNotificationPlaybackPosChanged, ERemConNotifyResponseChanged); + } + } + +void CPlayerInfoTarget::DoTrackReachedStart() + { + LOG_FUNC + + iTrackPosition = EStart; + + // if the ETrackReachedStart status is in the current event list + TInt pos = iPendingNotificationEventList.Find( ERegisterNotificationTrackReachedStart ); + if (pos != KErrNotFound) + { + iPendingNotificationEventList.Remove( pos ); + SendNotificationResponse(ERegisterNotificationTrackReachedStart, ERemConNotifyResponseChanged); + } + + pos = iPendingNotificationEventList.Find( ERegisterNotificationPlaybackPosChanged ); + if (pos != KErrNotFound) + { + iPendingNotificationEventList.Remove( pos ); + iPlaybackPositionInMilliseconds = 0; + SendNotificationResponse(ERegisterNotificationPlaybackPosChanged, ERemConNotifyResponseChanged); + } + } + +void CPlayerInfoTarget::DoSetPlaybackPosition(TUint32 aMilliseconds) + { + LOG_FUNC + + iPlaybackPositionInMilliseconds = aMilliseconds; + + // if the playback position is in the current Notification event list + TInt pos = iPendingNotificationEventList.Find( ERegisterNotificationPlaybackPosChanged ); + if (pos != KErrNotFound) + { + // a notification has been requested, now check if it is due + + TUint32 difference = (iPlaybackPositionInMilliseconds > iLastNotifiedPlaybackPositionInMilliseconds) ? + iPlaybackPositionInMilliseconds - iLastNotifiedPlaybackPositionInMilliseconds: + iLastNotifiedPlaybackPositionInMilliseconds - iPlaybackPositionInMilliseconds; + + if (difference >= iPlayBackIntervalInMilliseconds) + { + // Due now so send + iPendingNotificationEventList.Remove( pos ); + SendNotificationResponse(ERegisterNotificationPlaybackPosChanged, ERemConNotifyResponseChanged); + } + } + } + +void CPlayerInfoTarget::DoSetBatteryStatus(TTargetBatteryStatus aBatteryStatus) + { + LOG_FUNC + + TBool validStatus = ETrue; + if (aBatteryStatus < MPlayerEventsObserver::ENormal || + aBatteryStatus > MPlayerEventsObserver::EFullCharge) + { + LOG1(_L("Invalid battery status: %d"),aBatteryStatus); + validStatus = EFalse; + } + else + { + iBatteryStatus = aBatteryStatus; + } + + // if the battery status is in the current event list + TInt pos = iPendingNotificationEventList.Find( ERegisterNotificationBatteryStatusChanged ); + if (pos != KErrNotFound) + { + iPendingNotificationEventList.Remove( pos ); + if (validStatus) + { + SendNotificationResponse(ERegisterNotificationBatteryStatusChanged, ERemConNotifyResponseChanged); + } + } + } + +void CPlayerInfoTarget::SendError(TInt aError, TInt aOperationId, TRemConMessageSubType aSubType) + { + TInt error = 0; + RAvrcpIPCError response; + response.iError = aError; + TRAP(error, response.WriteL(iOutBuf)); // Don't send error if OOM + if (error == KErrNone) + InterfaceSelector().SendUnreliable(TUid::Uid(KRemConPlayerInformationUid), + aOperationId, ERemConResponse, aSubType, iOutBuf); + } +