os/mm/devsoundextensions/mmfcustominterfaces/SbcEncoderIntfc/SbcEncoderIntfcMsgHdlr/src/SbcEncoderIntfcMsgHdlr.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/mm/devsoundextensions/mmfcustominterfaces/SbcEncoderIntfc/SbcEncoderIntfcMsgHdlr/src/SbcEncoderIntfcMsgHdlr.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,493 @@
     1.4 +/*
     1.5 +* Copyright (c) 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:   Message handler for SBC encoder interface.
    1.18 +*
    1.19 +*/
    1.20 +
    1.21 +
    1.22 +
    1.23 +// INCLUDE FILES
    1.24 +#include <SbcEncoderIntfc.h>
    1.25 +#include "SbcEncoderIntfcMsgHdlr.h"
    1.26 +#include "SbcEncoderIntfcMsgs.h"
    1.27 +
    1.28 +// EXTERNAL DATA STRUCTURES
    1.29 +
    1.30 +// EXTERNAL FUNCTION PROTOTYPES
    1.31 +
    1.32 +// CONSTANTS
    1.33 +
    1.34 +// MACROS
    1.35 +
    1.36 +// LOCAL CONSTANTS AND MACROS
    1.37 +
    1.38 +// MODULE DATA STRUCTURES
    1.39 +
    1.40 +// LOCAL FUNCTION PROTOTYPES
    1.41 +
    1.42 +// FORWARD DECLARATIONS
    1.43 +
    1.44 +// ============================= LOCAL FUNCTIONS ===============================
    1.45 +
    1.46 +// ============================ MEMBER FUNCTIONS ===============================
    1.47 +
    1.48 +/**
    1.49 + * CSbcEncoderIntfcMsgHdlr::CSbcEncoderIntfcMsgHdlr
    1.50 + * C++ default constructor can NOT contain any code, that might leave.
    1.51 + */
    1.52 +CSbcEncoderIntfcMsgHdlr::CSbcEncoderIntfcMsgHdlr(
    1.53 +                         CSbcEncoderIntfc* aSbcEncoderIntfcCI) :
    1.54 +	CMMFObject(KUidSbcEncoderIntfc)
    1.55 +    {
    1.56 +    iSbcEncoderIntfcCI = aSbcEncoderIntfcCI;
    1.57 +    }
    1.58 +
    1.59 +/**
    1.60 + * CSbcEncoderIntfcMsgHdlr::ConstructL
    1.61 + * Symbian 2nd phase constructor can leave.
    1.62 + */
    1.63 +void CSbcEncoderIntfcMsgHdlr::ConstructL()
    1.64 +    {
    1.65 +    }
    1.66 +
    1.67 +/**
    1.68 + * CSbcEncoderIntfcMsgHdlr::NewL
    1.69 + * Two-phased constructor.
    1.70 + */
    1.71 +EXPORT_C CSbcEncoderIntfcMsgHdlr* CSbcEncoderIntfcMsgHdlr::NewL(
    1.72 +                                  TAny* aSbcEncoderIntfcCI)
    1.73 +    {
    1.74 +    CSbcEncoderIntfc* SbcEncoderIntfcCI =
    1.75 +                      (CSbcEncoderIntfc*)aSbcEncoderIntfcCI;
    1.76 +    CSbcEncoderIntfcMsgHdlr* self =
    1.77 +        new (ELeave) CSbcEncoderIntfcMsgHdlr(SbcEncoderIntfcCI);
    1.78 +    CleanupStack::PushL( self );
    1.79 +    self->ConstructL();
    1.80 +    CleanupStack::Pop( self );
    1.81 +    return self;
    1.82 +    }
    1.83 +
    1.84 +/**
    1.85 + * Destructor
    1.86 + */
    1.87 +EXPORT_C CSbcEncoderIntfcMsgHdlr::~CSbcEncoderIntfcMsgHdlr()
    1.88 +	{
    1.89 +	delete iDataCopyBuffer;
    1.90 +	delete iSbcEncoderIntfcCI;
    1.91 +	}
    1.92 +
    1.93 +/**
    1.94 + * CSbcEncoderIntfcMsgHdlr::HandleRequest
    1.95 + * Handles the messages from the proxy.
    1.96 + * Calls a subfunction which determines which custom interface to call.
    1.97 + * A subfunction is used to contain multiple leaving functions for a
    1.98 + * single trap.
    1.99 + * (other items were commented in a header).
   1.100 + */
   1.101 +EXPORT_C void CSbcEncoderIntfcMsgHdlr::HandleRequest(TMMFMessage& aMessage)
   1.102 +	{
   1.103 +    // debug panic
   1.104 +	ASSERT(aMessage.Destination().InterfaceId() == KUidSbcEncoderIntfc);
   1.105 +	TRAPD(error, DoHandleRequestL(aMessage));
   1.106 +	if(error)
   1.107 +		{
   1.108 +		aMessage.Complete(error);
   1.109 +		}
   1.110 +	}
   1.111 +
   1.112 +/**
   1.113 + * CSbcEncoderIntfcMsgHdlr::DoHandleRequestL
   1.114 + * Determines which custom interface to call.
   1.115 + * (other items were commented in a header).
   1.116 + */
   1.117 +void CSbcEncoderIntfcMsgHdlr::DoHandleRequestL(TMMFMessage& aMessage)
   1.118 +	{
   1.119 +	switch(aMessage.Function())
   1.120 +		{
   1.121 +		case ESbceimGetNumOfSupportedSamplingFrequencies:
   1.122 +			{
   1.123 +			DoGetNumOfSupportedSamplingFrequenciesL(aMessage);
   1.124 +			break;
   1.125 +			}
   1.126 +		case ESbceimGetSupportedSamplingFrequencies:
   1.127 +			{
   1.128 +			DoGetSupportedSamplingFrequenciesL(aMessage);
   1.129 +			break;
   1.130 +			}
   1.131 +		case ESbceimGetNumOfSupportedChannelModes:
   1.132 +			{
   1.133 +			DoGetNumOfSupportedChannelModesL(aMessage);
   1.134 +			break;
   1.135 +			}
   1.136 +		case ESbceimGetSupportedChannelModes:
   1.137 +			{
   1.138 +			DoGetSupportedChannelModesL(aMessage);
   1.139 +			break;
   1.140 +			}
   1.141 +		case ESbceimGetNumOfSupportedNumOfSubbands:
   1.142 +			{
   1.143 +			DoGetNumOfSupportedNumOfSubbandsL(aMessage);
   1.144 +			break;
   1.145 +			}
   1.146 +		case ESbceimGetSupportedNumOfSubbands:
   1.147 +			{
   1.148 +			DoGetSupportedNumOfSubbandsL(aMessage);
   1.149 +			break;
   1.150 +			}
   1.151 +		case ESbceimGetNumOfSupportedBlocks:
   1.152 +			{
   1.153 +			DoGetNumOfSupportedBlocksL(aMessage);
   1.154 +			break;
   1.155 +			}
   1.156 +		case ESbceimGetSupportedBlocks:
   1.157 +			{
   1.158 +			DoGetSupportedBlocksL(aMessage);
   1.159 +			break;
   1.160 +			}
   1.161 +		case ESbceimGetNumOfSupportedAllocationMethods:
   1.162 +			{
   1.163 +			DoGetNumOfSupportedAllocationMethodsL(aMessage);
   1.164 +			break;
   1.165 +			}
   1.166 +		case ESbceimGetSupportedAllocationMethods:
   1.167 +			{
   1.168 +			DoGetSupportedAllocationMethodsL(aMessage);
   1.169 +			break;
   1.170 +			}
   1.171 +		case ESbceimGetSupportedBitpoolRange:
   1.172 +			{
   1.173 +			DoGetSupportedBitpoolRangeL(aMessage);
   1.174 +			break;
   1.175 +			}
   1.176 +		case ESbceimApplyConfig:
   1.177 +			{
   1.178 +			DoApplyConfigL(aMessage);
   1.179 +			break;
   1.180 +			}
   1.181 +		default:
   1.182 +			{
   1.183 +			aMessage.Complete(KErrNotSupported);
   1.184 +			}
   1.185 +		}
   1.186 +	}
   1.187 +
   1.188 +/**
   1.189 + * CSbcEncoderIntfcMsgHdlr::DoGetNumOfSupportedSamplingFrequenciesL
   1.190 + * Handles the message from the proxy and calls the custom interface.
   1.191 + * The custom interface returns the data requested and this function writes
   1.192 + * it back to the proxy. It also creates a buffer and fills the sampling
   1.193 + * frequencies data to be returned in the subsequent call to
   1.194 + * DoGetSupportedSamplingFrequenciesL().
   1.195 + * (other items were commented in a header).
   1.196 + */
   1.197 +void CSbcEncoderIntfcMsgHdlr::DoGetNumOfSupportedSamplingFrequenciesL(
   1.198 +                              TMMFMessage& aMessage)
   1.199 +	{
   1.200 +	RArray<TUint> supSamplingFrequencies;
   1.201 +    CleanupClosePushL(supSamplingFrequencies);
   1.202 +
   1.203 +	TInt status = iSbcEncoderIntfcCI->GetSupportedSamplingFrequencies(
   1.204 +	                                  supSamplingFrequencies);
   1.205 +
   1.206 +    // store array in iDataCopyBuffer
   1.207 +	CreateBufFromUintArrayL(supSamplingFrequencies);
   1.208 +
   1.209 +	if (status == KErrNone)
   1.210 +    	{
   1.211 +	    TPckgBuf<TUint> pckg;
   1.212 +    	pckg() = supSamplingFrequencies.Count();
   1.213 +	    aMessage.WriteDataToClientL(pckg);
   1.214 +	    }
   1.215 +
   1.216 +    CleanupStack::PopAndDestroy(&supSamplingFrequencies);
   1.217 +    aMessage.Complete(status);
   1.218 +	}
   1.219 +
   1.220 +/**
   1.221 + * CSbcEncoderIntfcMsgHdlr::DoGetSupportedSamplingFrequenciesL
   1.222 + * Sends the sampling frequency data returned from the custom interface
   1.223 + * implementation to the client.
   1.224 + * (other items were commented in a header).
   1.225 + */
   1.226 +void CSbcEncoderIntfcMsgHdlr::DoGetSupportedSamplingFrequenciesL(
   1.227 +                              TMMFMessage& aMessage)
   1.228 +	{
   1.229 +    SendDataBufferToClientL(aMessage);
   1.230 +	}
   1.231 +
   1.232 +/**
   1.233 + * CSbcEncoderIntfcMsgHdlr::DoGetNumOfSupportedChannelModesL
   1.234 + * Handles the message from the proxy and calls the custom interface.
   1.235 + * The custom interface returns the data requested and this function writes
   1.236 + * it back to the proxy. It also creates a buffer and fills the sampling
   1.237 + * frequencies data to be returned in the subsequent call to
   1.238 + * DoGetSupportedChannelModesL().
   1.239 + * (other items were commented in a header).
   1.240 + */
   1.241 +void CSbcEncoderIntfcMsgHdlr::DoGetNumOfSupportedChannelModesL(
   1.242 +                              TMMFMessage& aMessage)
   1.243 +    {
   1.244 +    RArray<CSbcEncoderIntfc::TSbcChannelMode> supChannelModes;
   1.245 +    CleanupClosePushL(supChannelModes);
   1.246 +	TInt status =
   1.247 +	     iSbcEncoderIntfcCI->GetSupportedChannelModes(supChannelModes);
   1.248 +
   1.249 +    // store array in iDataCopyBuffer
   1.250 +	CreateBufFromUintArrayL(reinterpret_cast<RArray<TUint>&>(supChannelModes));
   1.251 +
   1.252 +	if (status == KErrNone)
   1.253 +    	{
   1.254 +	    TPckgBuf<TUint> pckg;
   1.255 +    	pckg() = supChannelModes.Count();
   1.256 +	    aMessage.WriteDataToClientL(pckg);
   1.257 +	    }
   1.258 +
   1.259 +    CleanupStack::PopAndDestroy(&supChannelModes);
   1.260 +    aMessage.Complete(status);
   1.261 +    }
   1.262 +
   1.263 +/**
   1.264 + * CSbcEncoderIntfcMsgHdlr::DoGetSupportedChannelModesL
   1.265 + * Sends the channel modes data returned from the custom interface
   1.266 + * implementation to the client.
   1.267 + * (other items were commented in a header).
   1.268 + */
   1.269 +void CSbcEncoderIntfcMsgHdlr::DoGetSupportedChannelModesL(
   1.270 +                              TMMFMessage& aMessage)
   1.271 +    {
   1.272 +    SendDataBufferToClientL(aMessage);
   1.273 +    }
   1.274 +
   1.275 +/**
   1.276 + * CSbcEncoderIntfcMsgHdlr::DoGetNumOfSupportedBlocksL
   1.277 + * Handles the message from the proxy and calls the custom interface.
   1.278 + * The custom interface returns the data requested and this function writes
   1.279 + * it back to the proxy. It also creates a buffer and fills the supported
   1.280 + * blocks data to be returned in the subsequent call to
   1.281 + * DoGetSupportedBlocksL().
   1.282 + * (other items were commented in a header).
   1.283 + */
   1.284 +void CSbcEncoderIntfcMsgHdlr::DoGetNumOfSupportedBlocksL(
   1.285 +                              TMMFMessage& aMessage)
   1.286 +    {
   1.287 +	RArray<TUint> supNumBlocks;
   1.288 +    CleanupClosePushL(supNumBlocks);
   1.289 +    
   1.290 +	TInt status = iSbcEncoderIntfcCI->GetSupportedNumOfBlocks(supNumBlocks);
   1.291 +
   1.292 +	CreateBufFromUintArrayL(supNumBlocks);
   1.293 +
   1.294 +	if (status == KErrNone)
   1.295 +    	{
   1.296 +	    TPckgBuf<TUint> pckg;
   1.297 +    	pckg() = supNumBlocks.Count();
   1.298 +	    aMessage.WriteDataToClientL(pckg);
   1.299 +	    }
   1.300 +
   1.301 +    CleanupStack::PopAndDestroy(&supNumBlocks);
   1.302 +    aMessage.Complete(status);
   1.303 +    }
   1.304 +
   1.305 +/**
   1.306 + * CSbcEncoderIntfcMsgHdlr::DoGetSupportedBlocksL
   1.307 + * Sends the supported blocks data returned from the custom interface
   1.308 + * implementation to the client.
   1.309 + * (other items were commented in a header).
   1.310 + */
   1.311 +void CSbcEncoderIntfcMsgHdlr::DoGetSupportedBlocksL(TMMFMessage& aMessage)
   1.312 +    {
   1.313 +    SendDataBufferToClientL(aMessage);
   1.314 +    }
   1.315 +
   1.316 +/**
   1.317 + * CSbcEncoderIntfcMsgHdlr::DoGetNumOfSupportedNumOfSubbandsL
   1.318 + * Handles the message from the proxy and calls the custom interface.
   1.319 + * The custom interface returns the data requested and this function writes
   1.320 + * it back to the proxy. It also creates a buffer and fills the supported
   1.321 + * subbands data to be returned in the subsequent call to
   1.322 + * DoGetSupportedNumOfSubbandsL().
   1.323 + * (other items were commented in a header).
   1.324 + */
   1.325 +void CSbcEncoderIntfcMsgHdlr::DoGetNumOfSupportedNumOfSubbandsL(
   1.326 +                              TMMFMessage& aMessage)
   1.327 +    {
   1.328 +	RArray<TUint> supNumSubbands;
   1.329 +	CleanupClosePushL(supNumSubbands);
   1.330 +
   1.331 +	TInt status = iSbcEncoderIntfcCI->GetSupportedNumOfSubbands(supNumSubbands);
   1.332 +
   1.333 +	CreateBufFromUintArrayL(supNumSubbands);
   1.334 +
   1.335 +	if (status == KErrNone)
   1.336 +    	{
   1.337 +	    TPckgBuf<TUint> pckg;
   1.338 +    	pckg() = supNumSubbands.Count();
   1.339 +	    aMessage.WriteDataToClientL(pckg);
   1.340 +	    }
   1.341 +
   1.342 +    CleanupStack::PopAndDestroy(&supNumSubbands);
   1.343 +    aMessage.Complete(status);
   1.344 +    }
   1.345 +
   1.346 +/**
   1.347 + * CSbcEncoderIntfcMsgHdlr::DoGetSupportedNumOfSubbandsL
   1.348 + * Sends the supported subbands data returned from the custom interface
   1.349 + * implementation to the client.
   1.350 + * (other items were commented in a header).
   1.351 + */
   1.352 +void CSbcEncoderIntfcMsgHdlr::DoGetSupportedNumOfSubbandsL(
   1.353 +                              TMMFMessage& aMessage)
   1.354 +    {
   1.355 +    SendDataBufferToClientL(aMessage);
   1.356 +    }
   1.357 +
   1.358 +/**
   1.359 + * CSbcEncoderIntfcMsgHdlr::DoGetNumOfSupportedAllocationMethodsL
   1.360 + * Handles the message from the proxy and calls the custom interface.
   1.361 + * The custom interface returns the data requested and this function writes
   1.362 + * it back to the proxy. It also creates a buffer and fills the supported
   1.363 + * allocation methods data to be returned in the subsequent call to
   1.364 + * DoGetSupportedAllocationMethodsL().
   1.365 + * (other items were commented in a header).
   1.366 + */
   1.367 +void CSbcEncoderIntfcMsgHdlr::DoGetNumOfSupportedAllocationMethodsL(
   1.368 +                              TMMFMessage& aMessage)
   1.369 +    {
   1.370 +    RArray<CSbcEncoderIntfc::TSbcAllocationMethod> supAllocMethods;
   1.371 +	CleanupClosePushL(supAllocMethods);
   1.372 +
   1.373 +	TInt status =
   1.374 +	     iSbcEncoderIntfcCI->GetSupportedAllocationMethods(supAllocMethods);
   1.375 +
   1.376 +    // store array in iDataCopyBuffer
   1.377 +	CreateBufFromUintArrayL(reinterpret_cast<RArray<TUint>&>(supAllocMethods));
   1.378 +
   1.379 +	if (status == KErrNone)
   1.380 +    	{
   1.381 +	    TPckgBuf<TUint> pckg;
   1.382 +    	pckg() = supAllocMethods.Count();
   1.383 +	    aMessage.WriteDataToClientL(pckg);
   1.384 +	    }
   1.385 +
   1.386 +    CleanupStack::PopAndDestroy(&supAllocMethods);
   1.387 +    aMessage.Complete(status);
   1.388 +    }
   1.389 +
   1.390 +/**
   1.391 + * CSbcEncoderIntfcMsgHdlr::DoGetSupportedAllocationMethodsL
   1.392 + * Sends the supported allocation methods data returned from the custom
   1.393 + * interface implementation to the client.
   1.394 + * (other items were commented in a header).
   1.395 + */
   1.396 +void CSbcEncoderIntfcMsgHdlr::DoGetSupportedAllocationMethodsL(
   1.397 +                              TMMFMessage& aMessage)
   1.398 +    {
   1.399 +    SendDataBufferToClientL(aMessage);
   1.400 +    }
   1.401 +
   1.402 +/**
   1.403 + * CSbcEncoderIntfcMsgHdlr::DoGetSupportedBitpoolRangeL
   1.404 + * Handles the message from the proxy and calls the custom interface.
   1.405 + * The custom interface returns the requested bitpool range and this function
   1.406 + * writes it back to the proxy.
   1.407 + * (other items were commented in a header).
   1.408 + */
   1.409 +void CSbcEncoderIntfcMsgHdlr::DoGetSupportedBitpoolRangeL(
   1.410 +                              TMMFMessage& aMessage)
   1.411 +    {
   1.412 +    TSbcEncoderBitpoolRange bitPoolRange;
   1.413 +    bitPoolRange.iMinSupportedBitpoolSize = 0;
   1.414 +    bitPoolRange.iMaxSupportedBitpoolSize = 0;
   1.415 +
   1.416 +	TInt status = iSbcEncoderIntfcCI->GetSupportedBitpoolRange(
   1.417 +	                                  bitPoolRange.iMinSupportedBitpoolSize,
   1.418 +	                                  bitPoolRange.iMaxSupportedBitpoolSize);
   1.419 +
   1.420 +	if (status == KErrNone)
   1.421 +    	{
   1.422 +	    TPckgBuf<TSbcEncoderBitpoolRange> pckg;
   1.423 +    	pckg() = bitPoolRange;
   1.424 +	    aMessage.WriteDataToClientL(pckg);
   1.425 +	    }
   1.426 +
   1.427 +    aMessage.Complete(status);
   1.428 +    }
   1.429 +
   1.430 +/**
   1.431 + * CSbcEncoderIntfcMsgHdlr::DoApplyConfigL
   1.432 + * Handles the message from the proxy to commit configuration settings and
   1.433 + * calls the custom interface method. The data passed from the proxy is read
   1.434 + * from the message and passed to the custom interface.
   1.435 + * (other items were commented in a header).
   1.436 + */
   1.437 +void CSbcEncoderIntfcMsgHdlr::DoApplyConfigL(TMMFMessage& aMessage)
   1.438 +	{
   1.439 +	TPckgBuf<TSbcEncoderConfig> pckgBuf;
   1.440 +	aMessage.ReadData1FromClientL(pckgBuf);
   1.441 +
   1.442 +	iSbcEncoderIntfcCI->SetSamplingFrequency(pckgBuf().iSamplingFrequency);
   1.443 +	iSbcEncoderIntfcCI->SetChannelMode(pckgBuf().iChannelMode);
   1.444 +	iSbcEncoderIntfcCI->SetNumOfSubbands(pckgBuf().iNumOfSubbands);
   1.445 +	iSbcEncoderIntfcCI->SetNumOfBlocks(pckgBuf().iNumOfBlocks);
   1.446 +	iSbcEncoderIntfcCI->SetAllocationMethod(pckgBuf().iAllocationMethod);
   1.447 +	iSbcEncoderIntfcCI->SetBitpoolSize(pckgBuf().iBitpoolSize);
   1.448 +
   1.449 +	TInt status = iSbcEncoderIntfcCI->ApplyConfig();
   1.450 +    aMessage.Complete(status);
   1.451 +	}
   1.452 +
   1.453 +/**
   1.454 + * CSbcEncoderIntfcMsgHdlr::CreateBufFromUintArrayL
   1.455 + * Utility function used to create a buffer and fill it with data from the
   1.456 + * array passed in.
   1.457 + * (other items were commented in a header).
   1.458 + */
   1.459 +void CSbcEncoderIntfcMsgHdlr::CreateBufFromUintArrayL(RArray<TUint>& aArray)
   1.460 +	{
   1.461 +	delete iDataCopyBuffer;
   1.462 +	iDataCopyBuffer = NULL;
   1.463 +	iDataCopyBuffer = CBufFlat::NewL(8);
   1.464 +
   1.465 +	RBufWriteStream stream;
   1.466 +	stream.Open(*iDataCopyBuffer);
   1.467 +	CleanupClosePushL(stream);
   1.468 +
   1.469 +	for (TInt i = 0; i < aArray.Count(); i++)
   1.470 +	    {	    	    
   1.471 +		stream.WriteUint32L(aArray[i]);
   1.472 +	    }
   1.473 +	    
   1.474 +	CleanupStack::PopAndDestroy(&stream);
   1.475 +	}	
   1.476 +
   1.477 +/**
   1.478 + * CSbcEncoderIntfcMsgHdlr::SendDataBufferToClientL
   1.479 + * Sends message with requested configuration data back to the client.
   1.480 + * (other items were commented in a header).
   1.481 + */
   1.482 +void CSbcEncoderIntfcMsgHdlr::SendDataBufferToClientL(TMMFMessage& aMessage)
   1.483 +    {
   1.484 +	if (!iDataCopyBuffer)
   1.485 +	    {
   1.486 +		User::Leave(KErrNotReady);
   1.487 +	    }
   1.488 +
   1.489 +	aMessage.WriteDataToClientL(iDataCopyBuffer->Ptr(0));
   1.490 +    aMessage.Complete(KErrNone);
   1.491 +    }
   1.492 +
   1.493 +
   1.494 +// ========================== OTHER EXPORTED FUNCTIONS =========================
   1.495 +
   1.496 +// End of File