1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/mm/devsoundextensions/drmaudioplayer/DRMPlayServer/src/DRMPlaySession.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,1088 @@
1.4 +/*
1.5 +* Copyright (c) 2005-2006 Nokia Corporation and/or its subsidiary(-ies).
1.6 +* All rights reserved.
1.7 +* This component and the accompanying materials are made available
1.8 +* under the terms of "Eclipse Public License v1.0"
1.9 +* which accompanies this distribution, and is available
1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.11 +*
1.12 +* Initial Contributors:
1.13 +* Nokia Corporation - initial contribution.
1.14 +*
1.15 +* Contributors:
1.16 +*
1.17 +* Description: DRM Play Session
1.18 +*
1.19 +*/
1.20 +
1.21 +
1.22 +#include "DRMPlaySession.h"
1.23 +#include <e32test.h>
1.24 +#include <e32std.h>
1.25 +#include <e32svr.h>
1.26 +#include <mmf/common/mmfcontrollerframework.h>
1.27 +#ifdef RD_TSP_CLIENT_MAPPER
1.28 +#include <tspclientmapper.h>
1.29 +#endif // #ifdef RD_TSP_CLIENT_MAPPER
1.30 +
1.31 +#ifdef _DEBUG
1.32 +#define DEP_PRN0(str) RDebug::Print(str)
1.33 +#define DEP_PRN1(str, v1) RDebug::Print(str, v1)
1.34 +#define DEP_PRN2(str, v1, v2) RDebug::Print(str, v1, v2)
1.35 +#else
1.36 +#define DEP_PRN0(str)
1.37 +#define DEP_PRN1(str, v1)
1.38 +#define DEP_PRN2(str, v1, v2)
1.39 +#endif // _DEBUG
1.40 +
1.41 +// This is the UID defined by custom interface builder
1.42 +const TUid KUidCustomInterfaceBuilderImpl = {0x10207A8E};
1.43 +
1.44 +// panic the client
1.45 +void CDRMPlayServerSession::PanicClient(const RMessage2 &aMessage, TInt aPanic) const
1.46 + {
1.47 + _LIT(KTxtServer,"DRM Play server");
1.48 + aMessage.Panic(KTxtServer,aPanic);
1.49 + }
1.50 +
1.51 +CDRMPlayServerSession::CDRMPlayServerSession(CDRMPlayServer* aServer)
1.52 +:iMessage2(NULL)
1.53 + {
1.54 + iServer=aServer;
1.55 + }
1.56 +
1.57 +CDRMPlayServerSession* CDRMPlayServerSession::NewL(CDRMPlayServer* aServer, const RMessage2& aMessage )
1.58 + {
1.59 + DEP_PRN0(_L("CDRMPlayServerSession::NewL"));
1.60 +
1.61 + CDRMPlayServerSession* self = new(ELeave) CDRMPlayServerSession(aServer);
1.62 + CleanupStack::PushL(self);
1.63 + self->ConstructL( aMessage );
1.64 + CleanupStack::Pop(self);
1.65 + return self;
1.66 + }
1.67 +
1.68 +#ifdef RD_TSP_CLIENT_MAPPER
1.69 +void CDRMPlayServerSession::ConstructL( const RMessage2& aMessage )
1.70 +#else
1.71 +void CDRMPlayServerSession::ConstructL( const RMessage2& /*aMessage*/ )
1.72 +#endif //RD_TSP_CLIENT_MAPPER
1.73 + {
1.74 +#ifdef RD_TSP_CLIENT_MAPPER
1.75 + iTSPClientMapper = CTspClientMapper::NewL();
1.76 + // Get client process ID
1.77 + RThread clientThread;
1.78 + RProcess clientProcess;
1.79 + // Open client thread and process handles
1.80 + User::LeaveIfError( aMessage.Client(clientThread) );
1.81 + User::LeaveIfError( clientThread.Process(clientProcess) );
1.82 + // Get process id
1.83 + iClientProcessId = clientProcess.Id();
1.84 + // Close client thread and client process handles
1.85 + clientThread.Close();
1.86 + clientProcess.Close();
1.87 +
1.88 + iTSPClientMapper->SetTspTargetClient(
1.89 + CTspClientMapper::ERegisteredClients,
1.90 + iClientProcessId );
1.91 +#endif // #ifdef RD_TSP_CLIENT_MAPPER
1.92 +
1.93 + // Increment number of sessions in server
1.94 + iServer->iClients++;
1.95 +
1.96 + DEP_PRN1(_L("CDRMPlayServerSession::iClients = %d"), iServer->iClients);
1.97 + }
1.98 +
1.99 +CDRMPlayServerSession::~CDRMPlayServerSession()
1.100 + {
1.101 + if(iMetaDataBuffer)
1.102 + {
1.103 + delete iMetaDataBuffer;
1.104 + iMetaDataBuffer = NULL;
1.105 + }
1.106 + // Delete any pending message objects
1.107 + // This will never happen, only happens when
1.108 + // Client closes the session in the middle of playback
1.109 + // but we cannot complete the message as RSession Handle is invalid
1.110 +/* if (iMessage2)
1.111 + {
1.112 + iMessage2->Complete(KErrCancel);
1.113 + }
1.114 +*/
1.115 + if(iMessage2)
1.116 + {
1.117 + delete iMessage2;
1.118 + iMessage2 = NULL;
1.119 + }
1.120 +
1.121 + // Delete play utility
1.122 + if (iPlayUtil)
1.123 + {
1.124 + delete iPlayUtil;
1.125 + iPlayUtil = NULL;
1.126 + }
1.127 + //delete iAsyncCallback;
1.128 + //iAsyncCallback = NULL;
1.129 +
1.130 +#ifdef RD_TSP_CLIENT_MAPPER
1.131 + if (iTSPClientMapper)
1.132 + {
1.133 +
1.134 + TInt status = iTSPClientMapper->RemoveTspTargetClient(
1.135 + CTspClientMapper::ERegisteredClients,
1.136 + iClientProcessId );
1.137 + DEP_PRN2(_L("CDRMPlayServerSession::~CDRMPlayServerSession:Unreg PID[%x]Status[%d]"), iClientProcessId.Id(), status );
1.138 + delete iTSPClientMapper;
1.139 + }
1.140 +#endif // #ifdef RD_TSP_CLIENT_MAPPER
1.141 +
1.142 + // Cancel any pending async messages.
1.143 + TInt index(0);
1.144 + CDRMCustomCommandAsyncAO* tempAO(NULL);
1.145 + for (;index < iActiveAsyncCustomCommands.Count(); index++)
1.146 + {
1.147 + tempAO = iActiveAsyncCustomCommands[0];
1.148 + if ( iCDRMCustomCommandAsyncAO2Phase == tempAO )
1.149 + {
1.150 + iCDRMCustomCommandAsyncAO2Phase = NULL;
1.151 + }
1.152 + delete tempAO;
1.153 + iActiveAsyncCustomCommands.Remove(0);
1.154 + }
1.155 + iActiveAsyncCustomCommands.Reset();
1.156 + iActiveAsyncCustomCommands.Close();
1.157 +
1.158 + delete iCDRMCustomCommandAsyncAO2Phase;
1.159 +
1.160 + iServer->iClients--;
1.161 +
1.162 + if(!iServer->iClients)
1.163 + {
1.164 + CActiveScheduler::Stop();
1.165 + }
1.166 + }
1.167 +
1.168 +void CDRMPlayServerSession::ServiceL(const RMessage2& aMessage)
1.169 + {
1.170 + TInt ret = KErrNone;
1.171 + TRAPD(err,ret = DispatchMessageL(aMessage));
1.172 + if (KErrNone != err)
1.173 + {
1.174 + ret = err;
1.175 + }
1.176 + if(iAsyncComplete == EFalse)
1.177 + {
1.178 + DEP_PRN1(_L("CDRMPlayServerSession::ServiceL - ret = %d"),ret);
1.179 + aMessage.Complete(ret);
1.180 + }
1.181 + }
1.182 +
1.183 +
1.184 +
1.185 +// service a client request; test the opcode and then do appropriate servicing
1.186 +TInt CDRMPlayServerSession::DispatchMessageL(const RMessage2 &aMessage)
1.187 + {
1.188 + TInt ret=KErrNone;
1.189 + iAsyncComplete= EFalse;
1.190 + DEP_PRN1(_L("CDRMPlayServerSession::DispatchMessageL:FnId[%d]"),aMessage.Function());
1.191 + switch (aMessage.Function())
1.192 + {
1.193 + case EDRMPlayServCreate:
1.194 + break;
1.195 + case EDRMPlayServNewFilePlayerL:
1.196 + iMessage = aMessage;
1.197 + NewFilePlayerL(aMessage);
1.198 + iAsyncComplete = ETrue;
1.199 + break;
1.200 + case EDRMPlayServNewDesPlayerL:
1.201 + iMessage = aMessage;
1.202 + NewDesPlayerL(aMessage);
1.203 + iAsyncComplete = ETrue;
1.204 + break;
1.205 + case EDRMPlayServNewDesPlayerReadOnlyL:
1.206 + iMessage = aMessage;
1.207 + NewDesPlayerReadOnlyL(aMessage);
1.208 + iAsyncComplete = ETrue;
1.209 + break;
1.210 + case EDRMPlayServNewPlayerL:
1.211 + NewPlayerL(aMessage);
1.212 + break;
1.213 + case EDRMPlayServOpenFile:
1.214 + iMessage = aMessage;
1.215 + OpenFileL(aMessage);
1.216 + iAsyncComplete = ETrue;
1.217 + break;
1.218 + case EDRMPlayServOpenFileByHandle:
1.219 + iMessage = aMessage;
1.220 + OpenFileByHandleL(aMessage);
1.221 + iAsyncComplete = ETrue;
1.222 + break;
1.223 + case EDRMPlayServOpenFileBySource:
1.224 + iMessage = aMessage;
1.225 + OpenFileBySourceL(aMessage);
1.226 + iAsyncComplete = ETrue;
1.227 + break;
1.228 + case EDRMPlayServOpenDes:
1.229 + iMessage = aMessage;
1.230 + OpenDesL(aMessage);
1.231 + iAsyncComplete = ETrue;
1.232 + break;
1.233 + case EDRMPlayServOpenUrl:
1.234 + iMessage = aMessage;
1.235 + OpenUrlL(aMessage);
1.236 + iAsyncComplete = ETrue;
1.237 + break;
1.238 + case EDRMPlayServPlay:
1.239 + iMessage = aMessage;
1.240 + if(iMessage2)
1.241 + {
1.242 + iMessage2->Complete(KErrCancel);
1.243 + delete iMessage2;
1.244 + iMessage2 = NULL;
1.245 + }
1.246 + iMessage2 = new (ELeave) RMessage2(aMessage);
1.247 + Play();
1.248 + iAsyncComplete = ETrue;
1.249 + break;
1.250 + case EDRMPlayServStop:
1.251 + if(iState == EStopped)
1.252 + break;
1.253 + if(iMessage2)
1.254 + {
1.255 + iMessage2->Complete(KErrCancel);
1.256 + delete iMessage2;
1.257 + iMessage2 = NULL;
1.258 + }
1.259 + Stop();
1.260 + break;
1.261 + case EDRMPlayServSetVolume:
1.262 + SetVolume(aMessage);
1.263 + break;
1.264 + case EDRMPlayServSetRepeats:
1.265 + SetRepeats(aMessage);
1.266 + break;
1.267 + case EDRMPlayServSetVolumeRamp:
1.268 + SetVolumeRamp(aMessage);
1.269 + break;
1.270 + case EDRMPlayServDuration:
1.271 + Duration(aMessage);
1.272 + break;
1.273 + case EDRMPlayServMaxVolume:
1.274 + ret = MaxVolume();
1.275 + break;
1.276 + case EDRMPlayServPause:
1.277 + ret = Pause();
1.278 + if(iMessage2)
1.279 + {
1.280 + iMessage2->Complete(KErrCancel);
1.281 + delete iMessage2;
1.282 + iMessage2 = NULL;
1.283 + }
1.284 + iAsyncComplete = EFalse;
1.285 + break;
1.286 + case EDRMPlayServClose:
1.287 + Close();
1.288 + break;
1.289 + case EDRMPlayServGetPosition:
1.290 + ret = GetPosition(aMessage);
1.291 + break;
1.292 + case EDRMPlayServSetPosition:
1.293 + SetPosition(aMessage);
1.294 + break;
1.295 + case EDRMPlayServSetPriority:
1.296 + ret = SetPriority(aMessage);
1.297 + break;
1.298 + case EDRMPlayServGetVolume:
1.299 + ret = GetVolume(aMessage);
1.300 + break;
1.301 + case EDRMPlayServGetNumberOfMetaDataEntries:
1.302 + ret = GetNumberOfMetaDataEntries(aMessage);
1.303 + break;
1.304 + case EDRMPlayServGetMetaDataEntry:
1.305 + GetMetaDataEntryL(aMessage);
1.306 + break;
1.307 + case EDRMPlayServClearPlayWindow:
1.308 + ret = ClearPlayWindow();
1.309 + break;
1.310 + case EDRMPlayServSetBalance:
1.311 + ret = SetBalance(aMessage);
1.312 + break;
1.313 + case EDRMPlayServGetBalance:
1.314 + ret = GetBalance(aMessage);
1.315 + break;
1.316 + case EDRMPlayServGetBitRate:
1.317 + ret = GetBitRate(aMessage);
1.318 + break;
1.319 + case EDRMPlayServRegisterForAudioLoadingNotification:
1.320 + iMessage = aMessage;
1.321 + RegisterForAudioLoadingNotification(aMessage);
1.322 + iAsyncComplete = ETrue;
1.323 + break;
1.324 + case EDRMPlayServGetAudioLoadingProgress:
1.325 + GetAudioLoadingProgressL(aMessage);
1.326 + break;
1.327 + case EDRMPlayServSetPlayWindow:
1.328 + SetPlayWindow(aMessage);
1.329 + break;
1.330 + case EDRMPlayServControllerImplementationInformation:
1.331 + ControllerImplementationInformationL(aMessage);
1.332 + break;
1.333 + case EDRMPlayServCustomCommandSyncWithReturn:
1.334 + case EDRMPlayServCustomCommandSyncWithoutReturn:
1.335 + CustomCommandSyncL(aMessage);
1.336 + break;
1.337 + case EDRMPlayServCustomCommandAsyncWithReturnStep1:
1.338 + case EDRMPlayServCustomCommandAsyncWithoutReturnStep1:
1.339 + CustomCommandAsyncStep1L(aMessage);
1.340 + // Setting this flag does not complete message in ServiceL,
1.341 + iAsyncComplete = ETrue;
1.342 + break;
1.343 + case EDRMPlayServCustomCommandAsyncWithReturnStep2:
1.344 + case EDRMPlayServCustomCommandAsyncWithoutReturnStep2:
1.345 + CustomCommandAsyncStep2L(aMessage);
1.346 + // Setting this flag does not complete message in ServiceL,
1.347 + iAsyncComplete = ETrue;
1.348 + break;
1.349 + case EDRMPlayServSetPriorityPreference:
1.350 + SetPriorityPreference(aMessage);
1.351 + break;
1.352 +
1.353 + default:
1.354 + PanicClient(aMessage, EBadRequest);
1.355 + break;
1.356 + }
1.357 + return ret;
1.358 + }
1.359 +
1.360 +void CDRMPlayServerSession::NewFilePlayerL(const RMessage2 aMessage)
1.361 + {
1.362 + TDataStructPckgBuf params;
1.363 +
1.364 + aMessage.Read(0,iCallbackState);
1.365 + aMessage.Read(1,params);
1.366 + aMessage.Read(2,iErrDurPckg);
1.367 + HBufC16* inputBuf = HBufC16::NewL(aMessage.GetDesLengthL(3));
1.368 + TPtr16 ptr = inputBuf->Des();
1.369 + aMessage.Read(3,ptr);
1.370 + const TDataStruct &theStruct = params();
1.371 + delete iPlayUtil;
1.372 + iPlayUtil = NULL;
1.373 + iPlayUtil = CMdaAudioPlayerUtility::NewFilePlayerL( inputBuf->Des(),
1.374 + *this,
1.375 + iPriority,
1.376 + iPref);
1.377 + delete inputBuf;
1.378 + }
1.379 +
1.380 +void CDRMPlayServerSession::NewDesPlayerL(const RMessage2 aMessage)
1.381 + {
1.382 + TDataStructPckgBuf thePckg;
1.383 + aMessage.Read(0,iCallbackState);
1.384 + aMessage.Read(1,thePckg);
1.385 + aMessage.Read(2,iErrDurPckg);
1.386 +
1.387 + delete iPlayUtil;
1.388 + iPlayUtil = NULL;
1.389 + iPlayUtil = CMdaAudioPlayerUtility::NewDesPlayerL(thePckg().iData,
1.390 + *this,
1.391 + iPriority,
1.392 + iPref);
1.393 +
1.394 + }
1.395 +
1.396 +void CDRMPlayServerSession::NewDesPlayerReadOnlyL(const RMessage2 aMessage)
1.397 + {
1.398 + TDataStructPckgBuf thePckg;
1.399 + aMessage.Read(0,iCallbackState);
1.400 + aMessage.Read(1,thePckg);
1.401 + aMessage.Read(2,iErrDurPckg);
1.402 +
1.403 + delete iPlayUtil;
1.404 + iPlayUtil = NULL;
1.405 + iPlayUtil = CMdaAudioPlayerUtility::NewDesPlayerReadOnlyL(thePckg().iData,
1.406 + *this,
1.407 + iPriority,
1.408 + iPref);
1.409 + }
1.410 +
1.411 +void CDRMPlayServerSession::NewPlayerL(const RMessage2 aMessage)
1.412 + {
1.413 +
1.414 + TDataStructPckgBuf thePckg;
1.415 + aMessage.Read(0,iCallbackState);
1.416 + aMessage.Read(1,thePckg);
1.417 + aMessage.Read(2,iErrDurPckg);
1.418 +
1.419 + delete iPlayUtil;
1.420 + iPlayUtil = NULL;
1.421 + iPlayUtil = CMdaAudioPlayerUtility::NewL(*this,
1.422 + iPriority,
1.423 + iPref);
1.424 + }
1.425 +
1.426 +void CDRMPlayServerSession::OpenFileL(const RMessage2 &aMessage)
1.427 + {
1.428 + //call mmfclientaudioplayer open file
1.429 + iFileHandleUsed = EFalse;
1.430 +
1.431 + aMessage.Read(0,iCallbackState);
1.432 + // Get the file length
1.433 + TInt len = aMessage.GetDesLengthL(1);
1.434 + HBufC* fileName = HBufC::NewLC(len);
1.435 + TPtr fileNamePtr = fileName->Des();
1.436 + aMessage.Read(1,fileNamePtr);
1.437 + aMessage.Read(2,iErrDurPckg);
1.438 + if(iPlayUtil)
1.439 + {
1.440 + iPlayUtil->OpenFileL(fileNamePtr);
1.441 + }
1.442 + CleanupStack::PopAndDestroy(fileName);
1.443 + }
1.444 +
1.445 +void CDRMPlayServerSession::OpenFileByHandleL(const RMessage2 &aMessage)
1.446 + {
1.447 + iFileHandleUsed = ETrue;
1.448 + TInt err = iFileHandle.AdoptFromClient(aMessage,1,3);
1.449 +
1.450 + aMessage.Read(0,iCallbackState);
1.451 + aMessage.Read(2,iErrDurPckg);
1.452 +
1.453 + if (err == KErrNone)
1.454 + {
1.455 + if(iPlayUtil)
1.456 + {
1.457 + iPlayUtil->OpenFileL(iFileHandle);
1.458 + }
1.459 + }
1.460 + else
1.461 + {
1.462 + User::Leave(err);
1.463 + }
1.464 + }
1.465 +
1.466 +void CDRMPlayServerSession::OpenFileBySourceL(const RMessage2 &/*aMessage*/)
1.467 + {
1.468 +
1.469 + }
1.470 +
1.471 +void CDRMPlayServerSession::OpenDesL(const RMessage2 &aMessage)
1.472 + {
1.473 + //call mmfclientaudioplayer OpenDesL
1.474 + TBuf8<50> aDes;
1.475 +
1.476 + aMessage.Read(0,iCallbackState);
1.477 + aMessage.Read(1,aDes);
1.478 + aMessage.Read(2,iErrDurPckg);
1.479 +
1.480 + if(iPlayUtil)
1.481 + {
1.482 + iPlayUtil->OpenDesL(aDes);
1.483 + }
1.484 + }
1.485 +
1.486 +void CDRMPlayServerSession::OpenUrlL(const RMessage2 &aMessage)
1.487 + {
1.488 + //call mmfclientaudioplayer OpenUrlL
1.489 + TUrlStructPckgBuf thePckg;
1.490 +
1.491 + aMessage.Read(0,iCallbackState);
1.492 + aMessage.Read(1,thePckg);
1.493 + aMessage.Read(2,iErrDurPckg);
1.494 +
1.495 + if(iPlayUtil)
1.496 + {
1.497 + iPlayUtil->OpenUrlL(thePckg().iUrl,
1.498 + thePckg().iIapId,
1.499 + thePckg().iMimeType);
1.500 + }
1.501 + }
1.502 +
1.503 +void CDRMPlayServerSession::Play()
1.504 + {
1.505 + //call mmfclientaudioplayer Play
1.506 + iState = EPlaying;
1.507 + if(iPlayUtil)
1.508 + {
1.509 + iPlayUtil->Play();
1.510 +#ifdef RD_TSP_CLIENT_MAPPER
1.511 + TInt status = iTSPClientMapper->SetTspTargetClientToOtherType(
1.512 + CTspClientMapper::EPlayingClients,
1.513 + iClientProcessId );
1.514 + DEP_PRN2(_L("CDRMPlayServerSession::Play:Change PID[%x]Status[%d]"), iClientProcessId.Id(), status );
1.515 +#endif // #ifdef RD_TSP_CLIENT_MAPPER
1.516 + }
1.517 + }
1.518 +
1.519 +void CDRMPlayServerSession::Stop()
1.520 + {
1.521 + //call mmfclientaudioplayer Stop
1.522 + if(iPlayUtil)
1.523 + {
1.524 + iPlayUtil->Stop();
1.525 +#ifdef RD_TSP_CLIENT_MAPPER
1.526 + TInt status = iTSPClientMapper->SetTspTargetClientToOtherType(
1.527 + CTspClientMapper::EStoppedClients,
1.528 + iClientProcessId );
1.529 + DEP_PRN2(_L("CDRMPlayServerSession::Stop:Change PID[%x]Status[%d]"), iClientProcessId.Id(), status );
1.530 +#endif // #ifdef RD_TSP_CLIENT_MAPPER
1.531 + }
1.532 + iState = EStopped;
1.533 + }
1.534 +
1.535 +void CDRMPlayServerSession::SetVolume(const RMessage2 & aMessage)
1.536 + {
1.537 + //call mmfclientaudioplayer SetVolume
1.538 + TInt theVolume = aMessage.Int0();
1.539 +
1.540 + if(iPlayUtil)
1.541 + {
1.542 + iPlayUtil->SetVolume(theVolume);
1.543 + }
1.544 + }
1.545 +
1.546 +void CDRMPlayServerSession::SetRepeats(const RMessage2 &aMessage)
1.547 + {
1.548 + //call mmfclientaudioplayer SetRepeats
1.549 + TInt theRepeatNumberOfTimes = aMessage.Int0();
1.550 + TTimeIntervalMicroSeconds theTrailingSilence;
1.551 +
1.552 + TPckgTTimeIntervalMicroSeconds theTrailingSilencePckg(theTrailingSilence);
1.553 + aMessage.Read(1,theTrailingSilencePckg);
1.554 +
1.555 + iPlayUtil->SetRepeats(theRepeatNumberOfTimes,theTrailingSilence);
1.556 + }
1.557 +
1.558 +void CDRMPlayServerSession::SetVolumeRamp(const RMessage2 &aMessage)
1.559 + {
1.560 + //call mmfclientaudioplayer SetVolumeRamp
1.561 + TTimeIntervalMicroSeconds theRampDuration;
1.562 + TPckgTTimeIntervalMicroSeconds theRampDurationPckg(theRampDuration);
1.563 + aMessage.Read(0,theRampDurationPckg);
1.564 +
1.565 + iPlayUtil->SetVolumeRamp(theRampDuration);
1.566 + }
1.567 +
1.568 +void CDRMPlayServerSession::Duration(const RMessage2& aMessage)
1.569 + {
1.570 + TTimeIntervalMicroSeconds theDuration;
1.571 + theDuration = iPlayUtil->Duration();
1.572 +
1.573 + TPckgBufTTimeIntervalMicroSeconds theDurationPckg(theDuration);
1.574 + aMessage.Write(0,theDurationPckg);
1.575 + }
1.576 +
1.577 +TInt CDRMPlayServerSession::MaxVolume()
1.578 + {
1.579 + TInt theMaxVolume;
1.580 + theMaxVolume = iPlayUtil->MaxVolume();
1.581 +
1.582 + return theMaxVolume;
1.583 + }
1.584 +
1.585 +// API Additions since version 7.0
1.586 +TInt CDRMPlayServerSession::Pause()
1.587 + {
1.588 + TInt ret = KErrNone;
1.589 + if(iPlayUtil)
1.590 + {
1.591 + ret = iPlayUtil->Pause();
1.592 + }
1.593 +
1.594 + // This message should not be completed here. It should be completed in ServiceL()
1.595 +/* if(iState == EPlaying)
1.596 + {
1.597 + iMessage.Complete(KErrNone);
1.598 + }*/
1.599 + iState = EStopped;
1.600 + return ret;
1.601 + }
1.602 +
1.603 +void CDRMPlayServerSession::Close()
1.604 + {
1.605 +
1.606 + if(iFileHandleUsed)
1.607 + iFileHandle.Close();
1.608 +
1.609 + iPlayUtil->Close();
1.610 + }
1.611 +
1.612 +TInt CDRMPlayServerSession::GetPosition(const RMessage2 &aMessage)
1.613 + {
1.614 + TInt ret;
1.615 + TTimeIntervalMicroSeconds thePosition;
1.616 +
1.617 + ret = iPlayUtil->GetPosition(thePosition);
1.618 +
1.619 +
1.620 + TPckgTTimeIntervalMicroSeconds thePositionPckg(thePosition);
1.621 + aMessage.Write(0,thePositionPckg);
1.622 +
1.623 + return ret;
1.624 + }
1.625 +
1.626 +void CDRMPlayServerSession::SetPosition(const RMessage2 &aMessage)
1.627 + {
1.628 + TTimeIntervalMicroSeconds thePosition;
1.629 + TPckgTTimeIntervalMicroSeconds thePositionPckg(thePosition);
1.630 + aMessage.Read(0,thePositionPckg);
1.631 + iPlayUtil->SetPosition(thePosition);
1.632 + }
1.633 +
1.634 +TInt CDRMPlayServerSession::SetPriority(const RMessage2 &aMessage)
1.635 + {
1.636 + TInt thePriority = aMessage.Int0();
1.637 + TMdaPriorityPreference thePref = (TMdaPriorityPreference)aMessage.Int1();
1.638 +
1.639 + TInt ret = iPlayUtil->SetPriority(thePriority,thePref);
1.640 +
1.641 + return ret;
1.642 + }
1.643 +
1.644 +TInt CDRMPlayServerSession::GetVolume(const RMessage2 &aMessage)
1.645 + {
1.646 + TInt theVolume;
1.647 + TInt ret = iPlayUtil->GetVolume(theVolume);
1.648 + TPckgBufTInt pckg(theVolume);
1.649 + aMessage.Write(0,pckg);
1.650 + return ret;
1.651 + }
1.652 +
1.653 +TInt CDRMPlayServerSession::GetNumberOfMetaDataEntries(const RMessage2 &aMessage)
1.654 + {
1.655 + TInt ret;
1.656 + TInt theNumOfMetaDataEntries;
1.657 +
1.658 + ret = iPlayUtil->GetNumberOfMetaDataEntries(theNumOfMetaDataEntries);
1.659 +
1.660 + TPckgBufTInt pckg(theNumOfMetaDataEntries);
1.661 + aMessage.Write(0,pckg);
1.662 +
1.663 + return ret;
1.664 + }
1.665 +
1.666 +
1.667 +void CDRMPlayServerSession::GetMetaDataEntryL(const RMessage2 &aMessage)
1.668 + {
1.669 + //Get the index of the required entry
1.670 + TInt theIndex = aMessage.Int0();
1.671 + CMMFMetaDataEntry* entry = iPlayUtil->GetMetaDataEntryL(theIndex);
1.672 + CleanupStack::PushL(entry);
1.673 + // Delete any existing buffer
1.674 + if (iMetaDataBuffer)
1.675 + {
1.676 + delete iMetaDataBuffer;
1.677 + iMetaDataBuffer = NULL;
1.678 + }
1.679 +
1.680 + // Create a buffer to hold the externalised entry
1.681 + iMetaDataBuffer = CBufFlat::NewL(32);
1.682 + RBufWriteStream s;
1.683 + s.Open(*iMetaDataBuffer);
1.684 + CleanupClosePushL(s);
1.685 + entry->ExternalizeL(s);
1.686 + CleanupStack::PopAndDestroy(2);//s, entry
1.687 +
1.688 + //Write the externalised data back to the client
1.689 + aMessage.Write(1,iMetaDataBuffer->Ptr(0));
1.690 + }
1.691 +
1.692 +
1.693 +TInt CDRMPlayServerSession::SetPlayWindow(const RMessage2 &aMessage)
1.694 + {
1.695 + TPlayWindowStructBuf buf;
1.696 + aMessage.Read(0,buf);
1.697 +
1.698 + TTimeIntervalMicroSeconds playStart = buf().iPlayStart;
1.699 + TTimeIntervalMicroSeconds playEnd = buf().iPlayEnd;
1.700 +
1.701 + TInt ret = iPlayUtil->SetPlayWindow(playStart,playEnd);
1.702 +
1.703 + return ret;
1.704 + }
1.705 +
1.706 +TInt CDRMPlayServerSession::ClearPlayWindow()
1.707 + {
1.708 + return iPlayUtil->ClearPlayWindow();
1.709 + }
1.710 +
1.711 +TInt CDRMPlayServerSession::SetBalance(const RMessage2 &aMessage)
1.712 + {
1.713 + TInt theBalance = aMessage.Int0();
1.714 + return iPlayUtil->SetBalance(theBalance);
1.715 + }
1.716 +
1.717 +TInt CDRMPlayServerSession::GetBalance(const RMessage2 &aMessage)
1.718 + {
1.719 + TInt theBalance;
1.720 + TInt ret;
1.721 +
1.722 + ret = iPlayUtil->GetBalance(theBalance);
1.723 +
1.724 + TPckgBufTInt pckg(theBalance);
1.725 + aMessage.Write(0,pckg);
1.726 +
1.727 + return ret;
1.728 + }
1.729 +
1.730 +TInt CDRMPlayServerSession::GetBitRate(const RMessage2 &aMessage)
1.731 + {
1.732 + TUint theBitRate;
1.733 + TInt ret;
1.734 +
1.735 + ret = iPlayUtil->GetBitRate(theBitRate);
1.736 +
1.737 + TPckgBufTUint pckg(theBitRate);
1.738 + aMessage.Write(0,pckg);
1.739 +
1.740 + return ret;
1.741 + }
1.742 +
1.743 +void CDRMPlayServerSession::RegisterForAudioLoadingNotification(const RMessage2 &aMessage)
1.744 + {
1.745 + aMessage.Read(0,iCallbackState);
1.746 +
1.747 + if(iCallbackState()==ELoadingStarted)
1.748 + {
1.749 + iPlayUtil->RegisterForAudioLoadingNotification(*this);
1.750 + }
1.751 + }
1.752 +
1.753 +void CDRMPlayServerSession::GetAudioLoadingProgressL(const RMessage2 &aMessage)
1.754 + {
1.755 + TInt thePercentProgress;
1.756 +
1.757 + iPlayUtil->GetAudioLoadingProgressL(thePercentProgress);
1.758 +
1.759 + TPckgBufTInt pckg(thePercentProgress);
1.760 +
1.761 + aMessage.Write(0,pckg);
1.762 + }
1.763 +
1.764 +void CDRMPlayServerSession::ControllerImplementationInformationL(const RMessage2 &aMessage)
1.765 + {
1.766 + const CMMFControllerImplementationInformation& x= iPlayUtil->ControllerImplementationInformationL();
1.767 +
1.768 + //for now just write Uid by to client
1.769 + typedef TPckg<TUid> TPckgTUid;
1.770 +
1.771 + TPckgTUid thePckg(x.Uid());
1.772 + aMessage.Write(0,thePckg);
1.773 + }
1.774 +
1.775 +
1.776 +void CDRMPlayServerSession::CustomCommandSyncL(const RMessage2 &aMessage)
1.777 + {
1.778 + DEP_PRN0(_L("CDRMPlayServerSession::CustomCommandSyncL:Enter"));
1.779 +
1.780 + TPckgCustomCommand thePckgCustomCommand;
1.781 + User::LeaveIfError(aMessage.Read(0,thePckgCustomCommand));
1.782 +
1.783 + HBufC8* dataTo1Buf(NULL);
1.784 + HBufC8* dataTo2Buf(NULL);
1.785 + HBufC8* dataFromBuf(NULL);
1.786 + TPtr8 ptr1(NULL, NULL);
1.787 + TPtr8 ptr2(NULL, NULL);
1.788 + TPtr8 ptr3(NULL, NULL);
1.789 +
1.790 + // Read data1
1.791 + dataTo1Buf = HBufC8::NewL(aMessage.GetDesLengthL(1));
1.792 + CleanupStack::PushL(dataTo1Buf);
1.793 + ptr1.Set(dataTo1Buf->Des());
1.794 + User::LeaveIfError(aMessage.Read(1,ptr1));
1.795 +
1.796 + // Check and filter the messages
1.797 + // Dont Allow Select Custom Commands
1.798 + if( !IsValidCustomCommandDestination(thePckgCustomCommand().iDestination().InterfaceId(), ptr1) )
1.799 + User::Leave(KErrAccessDenied);
1.800 +
1.801 + // Read data2
1.802 + dataTo2Buf = HBufC8::NewL(aMessage.GetDesLengthL(2));
1.803 + CleanupStack::PushL(dataTo2Buf);
1.804 + ptr2.Set(dataTo2Buf->Des());
1.805 + User::LeaveIfError(aMessage.Read(2,ptr2));
1.806 +
1.807 + if ( aMessage.Function() == EDRMPlayServCustomCommandSyncWithReturn )
1.808 + {
1.809 + // Read data3
1.810 + dataFromBuf = HBufC8::NewL(aMessage.GetDesLengthL(3));
1.811 + CleanupStack::PushL(dataFromBuf);
1.812 + ptr3.Set(dataFromBuf->Des());
1.813 + User::LeaveIfError(aMessage.Read(3,ptr3));
1.814 +/*
1.815 + RDebug::Print(_L("CDRMPlayServerSession::CustomCommandSync:IFId[%x]DestHndl[%x]Fn[%d]RetDesLen[%d]"),
1.816 + thePckgCustomCommand().iDestination().InterfaceId(),
1.817 + thePckgCustomCommand().iDestination().DestinationHandle(),
1.818 + thePckgCustomCommand().iFunction,
1.819 + ptr3.MaxLength());
1.820 +*/
1.821 + // Call CustomCommandSync on play util
1.822 + User::LeaveIfError(iPlayUtil->CustomCommandSync(
1.823 + thePckgCustomCommand().iDestination,
1.824 + thePckgCustomCommand().iFunction,
1.825 + ptr1,
1.826 + ptr2,
1.827 + ptr3));
1.828 + User::LeaveIfError(aMessage.Write(3,ptr3));
1.829 +
1.830 + // Free heap allocated for data3
1.831 + CleanupStack::PopAndDestroy(dataFromBuf);
1.832 + }
1.833 + else
1.834 + {
1.835 +/*
1.836 + RDebug::Print(_L("CDRMPlayServerSession::CustomCommandSync:IFId[%x]DestHndl[%x]Fn[%d]"),
1.837 + thePckgCustomCommand().iDestination().InterfaceId(),
1.838 + thePckgCustomCommand().iDestination().DestinationHandle(),
1.839 + thePckgCustomCommand().iFunction );
1.840 +*/
1.841 + // Call CustomCommandSync on play util
1.842 + User::LeaveIfError(iPlayUtil->CustomCommandSync(
1.843 + thePckgCustomCommand().iDestination,
1.844 + thePckgCustomCommand().iFunction,
1.845 + ptr1,
1.846 + ptr2));
1.847 + }
1.848 +
1.849 + // Free heap allocated for data2
1.850 + CleanupStack::PopAndDestroy(dataTo2Buf);
1.851 + // Free heap allocated for data1
1.852 + CleanupStack::PopAndDestroy(dataTo1Buf);
1.853 +
1.854 + DEP_PRN0(_L("CDRMPlayServerSession::CustomCommandSyncL:Exit"));
1.855 + }
1.856 +
1.857 +void CDRMPlayServerSession::CustomCommandAsyncStep1L( const RMessage2& aMessage )
1.858 + {
1.859 + DEP_PRN0(_L("CDRMPlayServerSession::CustomCommandAsyncStep1L:Enter"));
1.860 +
1.861 + // If there is a pending phase1, then there is something wrong.
1.862 + if ( iCDRMCustomCommandAsyncAO2Phase )
1.863 + {
1.864 + User::Leave(KErrAlreadyExists);
1.865 + }
1.866 +
1.867 + if ( aMessage.Function() == EDRMPlayServCustomCommandAsyncWithReturnStep1 )
1.868 + {
1.869 + iCDRMCustomCommandAsyncAO2Phase = CDRMCustomCommandAsyncAO::NewL(
1.870 + aMessage,
1.871 + CDRMCustomCommandAsyncAO::ECustomCommandWithResult,
1.872 + *this );
1.873 + }
1.874 + else /*if ( aMessage.Function() == EDRMPlayServCustomCommandAsyncWithoutReturnStep1 )*/
1.875 + {
1.876 + iCDRMCustomCommandAsyncAO2Phase = CDRMCustomCommandAsyncAO::NewL(
1.877 + aMessage,
1.878 + CDRMCustomCommandAsyncAO::ECustomCommandWithoutResult,
1.879 + *this );
1.880 + }
1.881 + // Get reference to data1 descriptor
1.882 + TPtr8 data1Ptr(iCDRMCustomCommandAsyncAO2Phase->GetData1FromClient()->Des());
1.883 +
1.884 + // Check and filter the messages
1.885 + // Dont Allow Select Custom Commands
1.886 + if( !IsValidCustomCommandDestination((iCDRMCustomCommandAsyncAO2Phase->GetMMFMessageDestinationPckg())().InterfaceId(), data1Ptr) )
1.887 + {
1.888 + User::Leave( KErrAccessDenied );
1.889 + }
1.890 +
1.891 + aMessage.Complete( KErrNone );
1.892 + DEP_PRN0(_L("CDRMPlayServerSession::CustomCommandAsyncStep1L:Exit"));
1.893 + }
1.894 +
1.895 +void CDRMPlayServerSession::CustomCommandAsyncStep2L( const RMessage2& aMessage )
1.896 + {
1.897 + DEP_PRN0(_L("CDRMPlayServerSession::CustomCommandAsyncStep2L:Enter"));
1.898 +
1.899 + // Read info from client session
1.900 + TPtr8 data1Ptr(NULL,NULL);
1.901 + TPtr8 data2Ptr(NULL,NULL);
1.902 + TPtr8 dataToClientPtr(NULL,NULL);
1.903 +
1.904 + // If there is no pending phase1, then there is something wrong.
1.905 + if ( !iCDRMCustomCommandAsyncAO2Phase )
1.906 + {
1.907 + User::Leave(KErrNotReady);
1.908 + }
1.909 +
1.910 + // Add custCmdAsyncAO object to array of async custom command objects
1.911 + iActiveAsyncCustomCommands.AppendL( iCDRMCustomCommandAsyncAO2Phase );
1.912 +
1.913 + // aMessage ownership is transferred to custCmdAsyncAO.
1.914 + // After succesful transfer, aMessage should not be completed
1.915 + // anywhere outside of this object.
1.916 + iCDRMCustomCommandAsyncAO2Phase->TransferOwnershipL(aMessage);
1.917 +
1.918 + CDRMCustomCommandAsyncAO* drmCCAsyncAO = iCDRMCustomCommandAsyncAO2Phase;
1.919 + iCDRMCustomCommandAsyncAO2Phase = NULL;
1.920 +
1.921 + // Get reference to descriptors
1.922 + data1Ptr.Set(drmCCAsyncAO->GetData1FromClient()->Des());
1.923 + data2Ptr.Set(drmCCAsyncAO->GetData2FromClient()->Des());
1.924 +
1.925 + // Make call on controller
1.926 + drmCCAsyncAO->SetActive();
1.927 + if ( aMessage.Function() == EDRMPlayServCustomCommandAsyncWithReturnStep2 )
1.928 + {
1.929 + // If date needs to be returned, get reference to the descriptor
1.930 + dataToClientPtr.Set(drmCCAsyncAO->GetDataToClient()->Des());
1.931 +/*
1.932 + RDebug::Print(_L("CDRMPlayServerSession::CustomCommandAsyncStep2L:IFId[%x]DestHndl[%x]Fn[%d]Data1[Len:%d:MaxLen:%d]Data2Len[Len:%d:MaxLen:%d]RetDesLen[Len:%d:MaxLen:%d]"),
1.933 + (drmCCAsyncAO->GetMMFMessageDestinationPckg())().InterfaceId(),
1.934 + (drmCCAsyncAO->GetMMFMessageDestinationPckg())().DestinationHandle(),
1.935 + drmCCAsyncAO->GetMMFMessageFunction(),
1.936 + data1Ptr.Length(),
1.937 + data1Ptr.MaxLength(),
1.938 + data2Ptr.Length(),
1.939 + data2Ptr.MaxLength(),
1.940 + dataToClientPtr.Length(),
1.941 + dataToClientPtr.MaxLength() );
1.942 +*/
1.943 + // Call CustomCommandAsync on play util
1.944 + iPlayUtil->CustomCommandAsync(
1.945 + drmCCAsyncAO->GetMMFMessageDestinationPckg(),
1.946 + drmCCAsyncAO->GetMMFMessageFunction(),
1.947 + data1Ptr,
1.948 + data2Ptr,
1.949 + dataToClientPtr,
1.950 + drmCCAsyncAO->iStatus );
1.951 + }
1.952 + else /*if ( aMessage.Function() == EDRMPlayServCustomCommandAsyncWithoutReturnStep2 )*/
1.953 + {
1.954 +/*
1.955 + RDebug::Print(_L("CDRMPlayServerSession::CustomCommandAsyncStep2L:IFId[%x]DestHndl[%x]Fn[%d]Data1[Len:%d:MaxLen:%d]Data2Len[Len:%d:MaxLen:%d]"),
1.956 + (drmCCAsyncAO->GetMMFMessageDestinationPckg())().InterfaceId(),
1.957 + (drmCCAsyncAO->GetMMFMessageDestinationPckg())().DestinationHandle(),
1.958 + drmCCAsyncAO->GetMMFMessageFunction(),
1.959 + data1Ptr.Length(),
1.960 + data1Ptr.MaxLength(),
1.961 + data2Ptr.Length(),
1.962 + data2Ptr.MaxLength() );
1.963 +*/
1.964 + // Call CustomCommandAsync on play util
1.965 + iPlayUtil->CustomCommandAsync(
1.966 + drmCCAsyncAO->GetMMFMessageDestinationPckg(),
1.967 + drmCCAsyncAO->GetMMFMessageFunction(),
1.968 + data1Ptr,
1.969 + data2Ptr,
1.970 + drmCCAsyncAO->iStatus );
1.971 + }
1.972 +
1.973 + DEP_PRN0(_L("CDRMPlayServerSession::CustomCommandAsyncStep2L:Exit"));
1.974 + }
1.975 +
1.976 +void CDRMPlayServerSession::MapcInitComplete(TInt aError, const TTimeIntervalMicroSeconds& aDuration)
1.977 + {
1.978 +
1.979 + DEP_PRN2(_L("CDRMPlayServerSession::MapcInitComplete :-> Status[%d] Duration[%d]"), aError, I64INT(aDuration.Int64()));
1.980 + //iMessage.Write aError & aDuration to client
1.981 + iCallbackState() = EInitComplete;
1.982 +
1.983 + iMessage.Write(0,iCallbackState);
1.984 +
1.985 + iErrDurPckg().iError = aError;
1.986 + iErrDurPckg().iDuration = aDuration;
1.987 +
1.988 + iMessage.Write(2,iErrDurPckg);
1.989 + iMessage.Complete(aError);
1.990 + iAsyncComplete= EFalse;
1.991 + }
1.992 +
1.993 +void CDRMPlayServerSession::MapcPlayComplete(TInt aError)
1.994 + {
1.995 + DEP_PRN1(_L("CDRMPlayServerSession::MapcPlayComplete :-> Error[%d]"), aError);
1.996 +
1.997 +#ifdef RD_TSP_CLIENT_MAPPER
1.998 + TInt status = iTSPClientMapper->SetTspTargetClientToOtherType(
1.999 + CTspClientMapper::EStoppedClients,
1.1000 + iClientProcessId );
1.1001 + DEP_PRN2(_L("CDRMPlayServerSession::MapcPlayComplete:Change PID[%x]Status[%d]"), iClientProcessId.Id(), status );
1.1002 +#endif // #ifdef RD_TSP_CLIENT_MAPPER
1.1003 +
1.1004 +
1.1005 + iState = EStopped;
1.1006 +
1.1007 + iCallbackState()= EPlayComplete;
1.1008 +/*
1.1009 + iMessage.Write(0,iCallbackState);
1.1010 + iErrDurPckg().iError = aError;
1.1011 + iErrDurPckg().iDuration = 0;
1.1012 + iMessage.Write(2,iErrDurPckg);
1.1013 + iMessage.Complete(aError);
1.1014 +*/
1.1015 + if ( iMessage2 )
1.1016 + {
1.1017 + //iMessage2. Write aError & aDuration to client
1.1018 + iCallbackState() = EPlayComplete;
1.1019 +
1.1020 + iMessage2->Write(0,iCallbackState);
1.1021 +
1.1022 + iErrDurPckg().iError = aError;
1.1023 + iErrDurPckg().iDuration = 0;
1.1024 + iMessage2->Write(2,iErrDurPckg);
1.1025 + iMessage2->Complete(aError);
1.1026 + delete iMessage2;
1.1027 + iMessage2 = NULL;
1.1028 + }
1.1029 +
1.1030 + iAsyncComplete= EFalse;
1.1031 + }
1.1032 +
1.1033 +
1.1034 +void CDRMPlayServerSession::MaloLoadingStarted()
1.1035 + {
1.1036 + //send event to client
1.1037 + iCallbackState() = ELoadingStarted;
1.1038 + iMessage.Write(0,iCallbackState);
1.1039 + iMessage.Complete(KErrNone);
1.1040 + iAsyncComplete= EFalse;
1.1041 + }
1.1042 +void CDRMPlayServerSession::MaloLoadingComplete()
1.1043 + {
1.1044 + //send event to client
1.1045 + iCallbackState() = ELoadingComplete;
1.1046 + iMessage.Write(0,iCallbackState);
1.1047 + iMessage.Complete(KErrNone);
1.1048 + iAsyncComplete= EFalse;
1.1049 + }
1.1050 +
1.1051 +void CDRMPlayServerSession::AsyncCustomCommandCompleted( CDRMCustomCommandAsyncAO* aObject)
1.1052 + {
1.1053 + TInt index = iActiveAsyncCustomCommands.Find( aObject );
1.1054 + // This should never happen. Else there is something wrong....
1.1055 + if ( index != KErrNotFound )
1.1056 + {
1.1057 + iActiveAsyncCustomCommands.Remove(index);
1.1058 + }
1.1059 + delete aObject;
1.1060 + }
1.1061 +
1.1062 +void CDRMPlayServerSession::SetPriorityPreference(const RMessage2 &aMessage)
1.1063 + {
1.1064 + iPriority = aMessage.Int0();
1.1065 + iPref = (TMdaPriorityPreference)aMessage.Int1();
1.1066 + }
1.1067 +
1.1068 +TBool CDRMPlayServerSession::IsValidCustomCommandDestination(TUid aDestinationUid, TDesC8& aParam)
1.1069 + {
1.1070 + TBool retValue(ETrue);
1.1071 + if (aDestinationUid == KUidInterfaceMMFDRMControl)
1.1072 + {
1.1073 + retValue = EFalse;
1.1074 + }
1.1075 + else if ( aDestinationUid == KUidCustomInterfaceBuilderImpl )
1.1076 + {
1.1077 + RDesReadStream stream(aParam);
1.1078 + CleanupClosePushL(stream);
1.1079 + TUid paramUid;
1.1080 + TRAPD(status, paramUid.iUid = stream.ReadInt32L());
1.1081 + CleanupStack::PopAndDestroy(&stream);
1.1082 + if ( (status == KErrNone ) && (paramUid == KUidAudioOutput) )
1.1083 + {
1.1084 + retValue = EFalse;
1.1085 + }
1.1086 + }
1.1087 + return retValue;
1.1088 + }
1.1089 +
1.1090 +// End of File
1.1091 +