--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/remotecontrol/avrcp/mediainformationapi/src/mediainformationapi.cpp Wed Oct 13 16:20:29 2010 +0300
@@ -0,0 +1,371 @@
+// 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:
+//
+
+/**
+ @file
+ @publishedAll
+ @released
+*/
+
+#include <bluetooth/logger.h>
+#include <remcon/avrcpspec.h>
+#include <remconmediainformationtarget.h>
+#include <remconmediainformationtargetobserver.h>
+#include <remconinterfaceselector.h>
+#include <avcframe.h>
+
+#include "mediainformation.h"
+
+#ifdef __FLOG_ACTIVE
+_LIT8(KLogComponent, LOG_COMPONENT_AVRCP_MEDIA_INFO);
+#endif
+
+EXPORT_C CRemConMediaInformationTarget* CRemConMediaInformationTarget::NewL(CRemConInterfaceSelector& aInterfaceSelector,
+ MRemConMediaInformationTargetObserver& aObserver)
+ {
+ LOG_STATIC_FUNC
+
+ CRemConMediaInformationTarget* self = new(ELeave) CRemConMediaInformationTarget(aInterfaceSelector, aObserver);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+CRemConMediaInformationTarget::CRemConMediaInformationTarget(CRemConInterfaceSelector& aInterfaceSelector,
+ MRemConMediaInformationTargetObserver& aObserver)
+: CRemConInterfaceBase(TUid::Uid(KRemConMediaInformationApiUid),
+ KMaxLengthMediaInformationMsg,
+ aInterfaceSelector,
+ ERemConClientTypeTarget),
+ iObserver(aObserver),
+ iAttributeIterator(iMediaAttributeIDs),
+ iMsgQueue(_FOFF(CRemConMediaInformationQueuedMessage, iLink))
+ {
+ }
+
+void CRemConMediaInformationTarget::ConstructL()
+ {
+ iResponse = new(ELeave)RRemConGetElementAttributesResponse();
+ TCallBack cb(&NextMessageCb, this);
+ iNextMessageCallBack = new (ELeave) CAsyncCallBack(cb, CActive::EPriorityStandard);
+ BaseConstructL();
+ }
+
+
+/** Destructor.
+
+@publishedAll
+@released
+*/
+EXPORT_C CRemConMediaInformationTarget::~CRemConMediaInformationTarget()
+ {
+ iMediaAttributeIDs.Close();
+ iResponse->Close();
+ delete iResponse;
+ iNextMessageCallBack->Cancel();
+ delete iNextMessageCallBack;
+ TSglQueIter<CRemConMediaInformationQueuedMessage> iter(iMsgQueue);
+ CRemConMediaInformationQueuedMessage* msg;
+ iter.SetToFirst();
+ while ((msg = iter++) != NULL)
+ {
+ iMsgQueue.Remove(*msg);
+ delete msg;
+ }
+ }
+
+/** Gets a pointer to a specific interface version.
+
+@return A pointer to the interface, NULL if not supported.
+@internalComponent
+@released
+*/
+TAny* CRemConMediaInformationTarget::GetInterfaceIf(TUid aUid)
+ {
+ TAny* ret = NULL;
+ if ( aUid == TUid::Uid(KRemConInterfaceIf1) )
+ {
+ ret = reinterpret_cast<TAny*>(
+ static_cast<MRemConInterfaceIf*>(this)
+ );
+ }
+
+ return ret;
+ }
+
+EXPORT_C TInt CRemConMediaInformationTarget::AttributeValue( TMediaAttributeId aAttributeId, TDesC8& aAttributeData )
+ {
+ // check that the values supplied were requested
+ if ( KErrNotFound == iMediaAttributeIDs.Find( aAttributeId ) )
+ {
+ return KErrNotFound;
+ }
+
+ REAResponse resp;
+ resp.iAttributeId = aAttributeId;
+ resp.iCharset = KUtf8MibEnum;
+ resp.iStringLen = aAttributeData.Length();
+ resp.iString = aAttributeData.Alloc();
+ if (resp.iString == NULL)
+ {
+ return KErrNoMemory;
+ }
+ TInt status = iResponse->iAttributes.Append(resp);
+ if (status != KErrNone)
+ {
+ resp.Close(); // make sure heap string is de-allocated
+ }
+ return status;
+ }
+
+// from MRemConInterfaceIf
+void CRemConMediaInformationTarget::SendError(TInt aError)
+ {
+ RBuf8 outBuf;
+ if (outBuf.Create(KAVCFrameMaxLength) != KErrNone)
+ {
+ // On OOM drop the message
+ return;
+ }
+
+ TInt error = 0;
+ RAvrcpIPCError response;
+ response.iError = aError;
+ TRAP(error, response.WriteL(outBuf)); // Don't send error if OOM
+ if (error == KErrNone)
+ {
+ InterfaceSelector().SendUnreliable(TUid::Uid(KRemConMediaInformationApiUid),
+ EGetElementAttributes, ERemConResponse, outBuf);
+ }
+ outBuf.Close();
+ }
+
+// from MRemConInterfaceIf
+void CRemConMediaInformationTarget::MrcibNewMessage(TUint aOperationId, const TDesC8& aData )
+ {
+ LOG1(_L("\taOperationId = 0x%02x"), aOperationId);
+ LOG1(_L("\taData.Length = %d"), aData.Length());
+
+ (void) aOperationId; // ignore warning about this variable being unused
+
+ if (!iInProgress && iMsgQueue.IsEmpty())
+ {
+ ProcessMessage(aData);
+ }
+ else
+ {
+ CRemConMediaInformationQueuedMessage* msg = NULL;
+ TRAPD(err, msg = CRemConMediaInformationQueuedMessage::NewL(aData));
+ if (err == KErrNone)
+ {
+ iMsgQueue.AddLast(*msg);
+ }
+ }
+ }
+
+void CRemConMediaInformationTarget::ProcessMessage(const TDesC8& aData)
+ {
+ iInProgress = ETrue;
+ // Try to read the incoming request
+ TInt error = KErrNone;
+ RRemConGetElementAttributesRequest request;
+ TRAP(error, request.ReadL(aData));
+
+ // Couldn't parse the request; tell them it was invalid
+ if (error != KErrNone)
+ {
+ request.Close();
+ return SendError(KErrAvrcpMetadataParameterNotFound);
+ }
+
+ // Specification section 5.3.1 (page 49) says unique id
+ // must be 0x0. All other values are currently reserved
+ if (request.iElement != 0)
+ {
+ request.Close();
+ return SendError(KErrAvrcpMetadataInvalidParameter);
+ }
+
+ // this may have been used by a previous GetElementAttributes, so
+ iMediaAttributeIDs.Reset();
+
+ if (request.iNumberAttributes == 0)
+ {
+ // spec says this is a request for all attribs
+ // current spec has 7 specified (0x01 to 0x07)
+ for (TInt i = 1; i <= 7; i++)
+ {
+ if (iMediaAttributeIDs.Append((TMediaAttributeId)i) != KErrNone)
+ {
+ request.Close();
+ return SendError(KErrAvrcpMetadataInternalError);
+ }
+ }
+ }
+ else
+ {
+ // No need to check request.iNumberAttributes == request.iAttributes.Count()
+ // as this must be correct or request.ReadL(aData) leaves
+ for (TInt i = 0; i < request.iNumberAttributes; i++)
+ {
+ TUint8 value = request.iAttributes[i];
+ if (value > 0 && value <= KMaxMediaAttributeValue )
+ {
+ if (iMediaAttributeIDs.Append((TMediaAttributeId)value) != KErrNone)
+ {
+ request.Close();
+ return SendError(KErrAvrcpMetadataInternalError);
+ }
+ }
+ }
+ }
+ request.Close();
+
+ // check that some valid attribute ids have been found
+ if (iMediaAttributeIDs.Count())
+ {
+ // if the client has not yet called Completed() on the last request
+ // clear the the attributes from the previous response
+ iResponse->Close();
+
+ // reset the interator to the start, as it may have been used before
+ iAttributeIterator.Start();
+
+ // call the client API to get the client value.
+ iObserver.MrcmitoGetCurrentlyPlayingMetadata(iAttributeIterator);
+ }
+ else
+ {
+ // no valid attribute ids found so return an error to bearer
+ SendError(KErrAvrcpMetadataParameterNotFound);
+ }
+ }
+
+// The client application has signaled that all attributes have been returned so
+// response can now be sent
+EXPORT_C void CRemConMediaInformationTarget::Completed()
+ {
+ if (!iInProgress)
+ {
+ return;
+ }
+ // Finalise response; update number of attributes returned
+ iResponse->iNumberAttributes = iResponse->iAttributes.Count();
+
+ //Check the bound of the number of attributes, zero is not permitted
+ if (iResponse->iNumberAttributes == 0)
+ {
+ return SendError(KErrAvrcpMetadataInternalError);
+ }
+
+ // Allocate a buffer for the formatted message
+ RBuf8 messageBuffer;
+ if ( messageBuffer.Create(iResponse->Size()) != KErrNone )
+ {
+ // On OOM drop the message
+ iResponse->Close();
+ return;
+ }
+
+ // send the result back to the CT
+ TInt error = KErrNone;
+ TRAP(error, iResponse->WriteL(messageBuffer));
+ if (error == KErrNone)
+ {
+ InterfaceSelector().SendUnreliable(TUid::Uid(KRemConMediaInformationApiUid),
+ EGetElementAttributes, ERemConResponse, messageBuffer);
+ }
+
+ // Make sure attribute list is reset for next time
+ iResponse->Close();
+ messageBuffer.Close();
+
+ iInProgress = EFalse;
+ if (!iMsgQueue.IsEmpty())
+ {
+ iNextMessageCallBack->CallBack();
+ }
+
+ }
+
+int CRemConMediaInformationTarget::NextMessageCb(TAny* aThis)
+ {
+ static_cast<CRemConMediaInformationTarget*>(aThis)->DoNextMessage();
+ return KErrNone;
+ }
+
+void CRemConMediaInformationTarget::DoNextMessage()
+ {
+ CRemConMediaInformationQueuedMessage* msg = iMsgQueue.First();
+ iMsgQueue.Remove(*msg);
+ ProcessMessage(msg->Data());
+ delete msg;
+ }
+
+EXPORT_C TMediaAttributeIter::TMediaAttributeIter(RArray<TMediaAttributeId>& aMediaAttributeIDs) :
+ iMediaAttributeIDs(aMediaAttributeIDs),
+ iterator(0)
+ {
+ }
+
+EXPORT_C void TMediaAttributeIter::Start()
+ {
+ iterator = 0;
+ }
+
+EXPORT_C TBool TMediaAttributeIter::Next(TMediaAttributeId& aId)
+ {
+ TInt count = iMediaAttributeIDs.Count();
+ if (iterator > count - 1)
+ {
+ return EFalse;
+ }
+ aId = iMediaAttributeIDs[iterator];
+ iterator++;
+ return ETrue;
+ }
+
+CRemConMediaInformationQueuedMessage* CRemConMediaInformationQueuedMessage::NewL(const TDesC8& aData)
+ {
+ CRemConMediaInformationQueuedMessage* self = new (ELeave) CRemConMediaInformationQueuedMessage();
+ CleanupStack::PushL(self);
+ self->ConstructL(aData);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+CRemConMediaInformationQueuedMessage::CRemConMediaInformationQueuedMessage()
+ {
+
+ }
+
+void CRemConMediaInformationQueuedMessage::ConstructL(const TDesC8& aData)
+ {
+ iData.CreateL(aData);
+ }
+
+CRemConMediaInformationQueuedMessage::~CRemConMediaInformationQueuedMessage()
+ {
+ iData.Close();
+ }
+
+const TDesC8& CRemConMediaInformationQueuedMessage::Data()
+ {
+ return iData;
+ }
+
+
+