mmdevicefw/mdf/src/audio/AudioDevice/audiodevice.cpp
changeset 0 79dd3e2336a0
equal deleted inserted replaced
-1:000000000000 0:79dd3e2336a0
       
     1 // Copyright (c) 2005-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 //
       
    15 
       
    16 #include <ecom/implementationproxy.h>
       
    17 #include <mmf/server/mmfdatabuffer.h>
       
    18 #include "audiodevice.hrh"
       
    19 #include "audiodevice.h"
       
    20 #include <e32debug.h>
       
    21 #include <mdf/mdfpuconfig.h>
       
    22 #include <mda/common/audio.h>
       
    23 
       
    24 // we need 16k to hold a pcm packet
       
    25 const TInt KBufferSize = 16384;
       
    26 
       
    27 const TInt KDefaultSampleRate = 8000;
       
    28 const TInt KDefaultNumberChannels = 1;
       
    29 _LIT(KAudioDevicePanic, "CAudioDevice Panic");
       
    30 
       
    31 enum TAudioDevicePanics
       
    32 	{
       
    33 	EObserverNotSet, 
       
    34 	EInvalidUsage
       
    35 	};
       
    36 	
       
    37 const TInt KInputPortIndex = 0;
       
    38 const TInt KOutputPortIndex = 1;
       
    39 	
       
    40 // ------------------------------------------------------------------------------------------	
       
    41 // CAudioDevice::CInput port class implementation
       
    42 
       
    43 	
       
    44 CAudioDevice::CInputPort::CInputPort(CAudioDevice& aParent) 
       
    45 	: CActive(EPriorityNormal),
       
    46 	  iParent(aParent),
       
    47 	  iSampleRate(KDefaultSampleRate),
       
    48 	  iChannels(KDefaultNumberChannels),
       
    49 	  iBufferSize(KBufferSize)
       
    50 	{
       
    51 	}
       
    52 		
       
    53 CAudioDevice::CInputPort::~CInputPort()
       
    54 	{
       
    55 	Cancel();
       
    56 	iBuffers.Close();
       
    57 	}
       
    58 
       
    59 CAudioDevice::CInputPort* CAudioDevice::CInputPort::NewL(CAudioDevice& aParent)
       
    60 	{
       
    61 	CInputPort* self = new (ELeave) CInputPort(aParent);
       
    62 	CleanupStack::PushL(self);
       
    63 	self->ConstructL();
       
    64 	CleanupStack::Pop(self);
       
    65 	return self;
       
    66 	}
       
    67 
       
    68 void CAudioDevice::CInputPort::ConstructL()
       
    69 	{
       
    70 	CActiveScheduler::Add(this);	
       
    71 	}
       
    72 
       
    73 TInt CAudioDevice::CInputPort::MipConfigure(const TPuConfig& aConfig)
       
    74 	{
       
    75 	if (aConfig.Uid() == TUid::Uid(KUidTTaskConfig))
       
    76 		{
       
    77 		const TTaskConfig* config = TPuTaskConfig::GetStructure(aConfig);	
       
    78 	
       
    79 		iSampleRate = config->iRate;
       
    80 		iChannels = (config->iStereoMode & ETaskMono)? 1 : 2;
       
    81 		iInterleaved = (config->iStereoMode & ETaskInterleaved)?ETrue : EFalse;
       
    82 		return KErrNone;
       
    83 		}
       
    84 	
       
    85 	if (aConfig.Uid() == TUid::Uid(KUidTTaskConfig2))
       
    86 		{
       
    87 		const TTaskConfig2* config = TPuTaskConfig2::GetStructure(aConfig);	
       
    88 	
       
    89 		iSampleRate = config->iRate;
       
    90 		iChannels = config->iNumberOfChannels;
       
    91 		iInterleaved = (config->iStereoMode & ETaskInterleaved)?ETrue : EFalse;
       
    92 		return KErrNone;
       
    93 		}	
       
    94 		
       
    95 	return KErrNotSupported;
       
    96 	}
       
    97 
       
    98 TInt CAudioDevice::CInputPort::MipGetConfig(TPuConfig& /*aConfig*/)
       
    99 	{
       
   100 	return KErrNotSupported;
       
   101 	}
       
   102 
       
   103 TInt CAudioDevice::CInputPort::MipTunnelRequest(const MMdfOutputPort& aOutputPortToBeConnectedTo,
       
   104 			TTunnelFlags& /*aTunnelFlags*/, TSupplierType& /*aSupplierType*/)
       
   105 	{
       
   106 	if ((iParent.State()!=EProcessingUnitLoaded) && (!iStopped))
       
   107 		{
       
   108 		// invalid state
       
   109 		return EInvalidState;
       
   110 		}
       
   111 	
       
   112 	if (iPortConnectedTo)
       
   113 		{
       
   114 		// the port is already connected, return an error
       
   115 		return EPortAlreadyTunnelled;
       
   116 		}
       
   117 	iPortConnectedTo = const_cast<MMdfOutputPort*>(&aOutputPortToBeConnectedTo);
       
   118 	return KErrNone;
       
   119 	}
       
   120 
       
   121 void CAudioDevice::CInputPort::MipWriteData(CMMFBuffer& aInputBuffer)
       
   122 	{
       
   123 	TInt err = iBuffers.Append(&aInputBuffer);
       
   124 	if (err == KErrNone)
       
   125 		{
       
   126 		if (iParent.State() == EProcessingUnitExecuting && !IsActive())
       
   127 			{
       
   128 			SetActive();
       
   129 			TRequestStatus* status = &iStatus;
       
   130 			User::RequestComplete(status, KErrNone);
       
   131 			}
       
   132 		}
       
   133 	else
       
   134 		{
       
   135 		if (iObserver)
       
   136 			{
       
   137 			iObserver->MipoWriteDataComplete(this, &aInputBuffer, err);
       
   138 			}
       
   139 		}
       
   140 	}
       
   141 
       
   142 void CAudioDevice::CInputPort::Execute()
       
   143 	{
       
   144 	if (!IsActive() && iBuffers.Count()>0)
       
   145 		{
       
   146 		SetActive();
       
   147 		TRequestStatus* status = &iStatus;
       
   148 		User::RequestComplete(status, KErrNone);
       
   149 		}
       
   150 	}
       
   151 
       
   152 TBool CAudioDevice::CInputPort::MipIsTunnelled() const
       
   153 	{
       
   154 	if (iPortConnectedTo)
       
   155 		{
       
   156 		return ETrue;
       
   157 		}
       
   158 	else
       
   159 		{
       
   160 		return EFalse;			
       
   161 		}
       
   162 	}
       
   163 
       
   164 TInt CAudioDevice::CInputPort::MipIndex() const
       
   165 	{
       
   166 	return KInputPortIndex;
       
   167 	}
       
   168 	
       
   169 CMMFBuffer* CAudioDevice::CInputPort::MipCreateBuffer(TInt /*aBufferSize*/)
       
   170 	{
       
   171 	__ASSERT_ALWAYS(EFalse, User::Panic(KAudioDevicePanic, EInvalidUsage));
       
   172 	return NULL;
       
   173 	}
       
   174 
       
   175 TInt CAudioDevice::CInputPort::MipUseBuffer(CMMFBuffer& /*aBuffer*/)
       
   176 	{
       
   177 	return KErrNone;
       
   178 	}
       
   179 
       
   180 TInt CAudioDevice::CInputPort::MipFreeBuffer(CMMFBuffer* /*aBuffer*/)
       
   181 	{
       
   182 	return KErrNone;
       
   183 	}
       
   184 	
       
   185 void CAudioDevice::CInputPort::MipDisconnectTunnel()
       
   186 	{
       
   187 	}
       
   188 
       
   189 void CAudioDevice::CInputPort::MipRestartTunnel()
       
   190 	{
       
   191 	}
       
   192 
       
   193 TUint32 CAudioDevice::CInputPort::MipBufferSize() const
       
   194 	{
       
   195 	return iBufferSize;
       
   196 	}
       
   197 
       
   198 void CAudioDevice::CInputPort::Pause()
       
   199 	{
       
   200 	if (iParent.SoundDevice().Handle())
       
   201 		{
       
   202 		iParent.SoundDevice().PausePlayBuffer();
       
   203 		}
       
   204 	}
       
   205 	
       
   206 void CAudioDevice::CInputPort::Stop()
       
   207 	{
       
   208 	Cancel();	
       
   209 	}
       
   210 	
       
   211 TInt CAudioDevice::CInputPort::MipCreateCustomInterface(TUid aUid)
       
   212 	{
       
   213 	if (aUid.iUid == KMmfPlaySettingsCustomInterface)
       
   214 		{
       
   215 		return KErrNone;
       
   216 		}
       
   217 	return KErrNotSupported;	
       
   218 	}
       
   219 
       
   220 TAny* CAudioDevice::CInputPort::MipCustomInterface(TUid aUid)
       
   221 	{
       
   222 	if (aUid.iUid == KMmfPlaySettingsCustomInterface)
       
   223 		{
       
   224 		return static_cast<MPlayCustomInterface*>(this);
       
   225 		}
       
   226 	return NULL;
       
   227 	}
       
   228 	
       
   229 void CAudioDevice::CInputPort::SetVolume(TUint aVolume)
       
   230 	{
       
   231 	iVolume = aVolume;
       
   232 	}
       
   233 
       
   234 TUint CAudioDevice::CInputPort::Volume()
       
   235 	{
       
   236 	return iVolume;
       
   237 	}
       
   238 
       
   239 TUint CAudioDevice::CInputPort::BytesPlayed()
       
   240 	{
       
   241 	return iBytesPlayed;
       
   242 	}
       
   243 
       
   244 void CAudioDevice::CInputPort::SetVolumeRamp(const TTimeIntervalMicroSeconds& aRampDuration)
       
   245 	{
       
   246 	iRampDuration = aRampDuration;
       
   247 	}
       
   248 
       
   249 TTimeIntervalMicroSeconds& CAudioDevice::CInputPort::VolumeRamp()
       
   250 	{
       
   251 	return iRampDuration;
       
   252 	}
       
   253 
       
   254 void CAudioDevice::CInputPort::RunL()
       
   255 	{
       
   256 	if (iCurrentBuffer != NULL)
       
   257 		{
       
   258 		// If we've been signalled with a buffer, callback that we've completed the writing of the
       
   259 		// buffer
       
   260 		if (iObserver)
       
   261 			{		
       
   262 			iObserver->MipoWriteDataComplete(this, iCurrentBuffer, iStatus.Int());
       
   263 			if (iCurrentBuffer->LastBuffer())
       
   264 				{
       
   265 				iParent.Observer()->ExecuteComplete(&iParent, KErrUnderflow);
       
   266 				iParent.SoundDevice().Close();
       
   267 				}
       
   268 			}
       
   269 		iCurrentBuffer = NULL;
       
   270 		}
       
   271 	// only process the next buffer if there is no error
       
   272 	// error callbacks were handled in the previous block
       
   273 	if (iStatus == KErrNone)
       
   274 		{
       
   275 		if (iBuffers.Count()>0)
       
   276 			{
       
   277 			iCurrentBuffer = iBuffers[0];
       
   278 			iBuffers.Remove(0);
       
   279 			
       
   280 			if (CMMFBuffer::IsSupportedDataBuffer(iCurrentBuffer->Type()))
       
   281 				{
       
   282  				TDes8& aBufferDes = (static_cast<CMMFDataBuffer*>(iCurrentBuffer))->Data();
       
   283  				iStatus = KRequestPending;
       
   284 				iParent.SoundDevice().PlayData(iStatus, aBufferDes);
       
   285 				SetActive();
       
   286 				}
       
   287 			}
       
   288 		}
       
   289 	}
       
   290 
       
   291 void CAudioDevice::CInputPort::DoCancel()
       
   292 	{
       
   293 	if (iParent.SoundDevice().Handle())
       
   294 		{
       
   295 		iParent.SoundDevice().CancelPlayData();
       
   296 		iParent.SoundDevice().FlushPlayBuffer();
       
   297 		}
       
   298 	}
       
   299 	
       
   300 // CAudioDevice::CInput port class implementation
       
   301 CAudioDevice::COutputPort::COutputPort(CAudioDevice& aParent) 
       
   302 	: CActive(EPriorityNormal),
       
   303 	iParent(aParent),
       
   304 	iSampleRate(KDefaultSampleRate),
       
   305 	iChannels(KDefaultNumberChannels),
       
   306 	iBufferSize(KBufferSize)
       
   307 	{	
       
   308 	}
       
   309 
       
   310 TInt CAudioDevice::CInputPort::SampleRate()
       
   311 	{
       
   312 	return iSampleRate;
       
   313 	}
       
   314 	
       
   315 TInt CAudioDevice::CInputPort::Channels()
       
   316 	{
       
   317 	return iChannels;
       
   318 	}
       
   319 
       
   320 void CAudioDevice::CInputPort::MipInitialize()
       
   321 	{
       
   322 	// Nothing to do
       
   323 	}
       
   324 	
       
   325 CAudioDevice::COutputPort* CAudioDevice::COutputPort::NewL(CAudioDevice& aParent)
       
   326 	{
       
   327 	COutputPort* self = new (ELeave) COutputPort(aParent);
       
   328 	CleanupStack::PushL(self);
       
   329 	self->ConstructL();
       
   330 	CleanupStack::Pop(self);
       
   331 	return self;
       
   332 	}
       
   333 
       
   334 void CAudioDevice::COutputPort::ConstructL()
       
   335 	{
       
   336 	CActiveScheduler::Add(this);	
       
   337 	}
       
   338 
       
   339 TInt CAudioDevice::COutputPort::MopConfigure(const TPuConfig& aConfig)
       
   340 	{
       
   341 	if (aConfig.Uid() == TUid::Uid(KUidTTaskConfig))
       
   342 		{
       
   343 		const TTaskConfig* config = TPuTaskConfig::GetStructure(aConfig);	
       
   344 	
       
   345 		iSampleRate = config->iRate;
       
   346 		iChannels = (config->iStereoMode & ETaskMono)? 1 : 2;
       
   347 		iInterleaved = (config->iStereoMode & ETaskInterleaved)?ETrue : EFalse;
       
   348 		return KErrNone;
       
   349 		}
       
   350 		
       
   351 	if (aConfig.Uid() == TUid::Uid(KUidTTaskConfig2))
       
   352 		{
       
   353 		const TTaskConfig2* config = TPuTaskConfig2::GetStructure(aConfig);	
       
   354 	
       
   355 		iSampleRate = config->iRate;
       
   356 		iChannels = config->iNumberOfChannels;
       
   357 		iInterleaved = (config->iStereoMode & ETaskInterleaved)?ETrue : EFalse;
       
   358 		return KErrNone;
       
   359 		}	
       
   360 	return KErrNotSupported;
       
   361 	}
       
   362 	
       
   363 TInt CAudioDevice::COutputPort::MopGetConfig(TPuConfig& /*aConfig*/)
       
   364 	{
       
   365 	return KErrNotSupported;
       
   366 	}
       
   367 
       
   368 void CAudioDevice::COutputPort::MopInitialize()
       
   369 	{
       
   370 	// Nothing to do
       
   371 	}
       
   372 
       
   373 TInt CAudioDevice::COutputPort::MopTunnelRequest(const MMdfInputPort& /*aInputPortToBeConnectedTo*/,
       
   374 	TTunnelFlags& /*aTunnelFlags*/, TSupplierType& /*aSupplierType*/)
       
   375 	{
       
   376 	return KErrNone;
       
   377 	}
       
   378 
       
   379 void CAudioDevice::COutputPort::MopReadData(CMMFBuffer& aOutputBuffer)
       
   380 	{
       
   381 	TInt err = iBuffers.Append(&aOutputBuffer);
       
   382 	if (err == KErrNone)
       
   383 		{
       
   384 		if ((iParent.State() == EProcessingUnitExecuting || iParent.State() == EProcessingUnitPaused) && !IsActive())
       
   385 			{
       
   386 			SetActive();
       
   387 			TRequestStatus* status = &iStatus;
       
   388 			User::RequestComplete(status, KErrNone);	
       
   389 			}		
       
   390 		}
       
   391 	else
       
   392 		{
       
   393 		if (iObserver)
       
   394 			{
       
   395 			iObserver->MopoReadDataComplete(this, &aOutputBuffer, err);
       
   396 			}
       
   397 		}
       
   398 	}
       
   399 
       
   400 TBool CAudioDevice::COutputPort::MopIsTunnelled() const
       
   401 	{
       
   402 	return EFalse;	
       
   403 	}
       
   404 
       
   405 TInt CAudioDevice::COutputPort::MopIndex() const
       
   406 	{
       
   407 	return KOutputPortIndex;
       
   408 	}
       
   409 	
       
   410 CMMFBuffer* CAudioDevice::COutputPort::MopCreateBuffer(TInt /*aBufferSize*/)
       
   411 	{
       
   412 	return NULL;
       
   413 	}
       
   414 	
       
   415 TInt CAudioDevice::COutputPort::MopUseBuffer(CMMFBuffer& /*aBuffer*/) 
       
   416 	{
       
   417 	return KErrNone;
       
   418 	}
       
   419 
       
   420 TInt CAudioDevice::COutputPort::MopFreeBuffer(CMMFBuffer* /*aBuffer*/) 
       
   421 	{
       
   422 	return KErrNone;
       
   423 	}
       
   424 
       
   425 void CAudioDevice::COutputPort::Execute()
       
   426 	{
       
   427 	if (!IsActive() && iBuffers.Count()>0)
       
   428 		{
       
   429 		SetActive();
       
   430 		TRequestStatus* status = &iStatus;
       
   431 		User::RequestComplete(status, KErrNone);
       
   432 		}
       
   433 	}
       
   434 	
       
   435 void CAudioDevice::COutputPort::Pause()
       
   436 	{
       
   437 	if(iParent.SoundDevice().Handle())
       
   438 		{
       
   439 		iParent.SoundDevice().FlushRecordBuffer();
       
   440 		}	
       
   441 	}
       
   442 	
       
   443 void CAudioDevice::COutputPort::Stop()
       
   444 	{
       
   445 	Cancel();
       
   446 	}
       
   447 
       
   448 void CAudioDevice::COutputPort::MopDisconnectTunnel()
       
   449 	{
       
   450 	// Find the last buffer in the array and set it as the 'LastBuffer'
       
   451 	if(iBuffers.Count() > 0)
       
   452 		{
       
   453 		(iBuffers[iBuffers.Count() - 1])->SetLastBuffer(ETrue);		
       
   454 		}
       
   455 	// Still have to send callback and cancel driver
       
   456 	iObserver->MopoDisconnectTunnelComplete(this, KErrNone);
       
   457 	iParent.SoundDevice().CancelRecordData();
       
   458 	}
       
   459 	
       
   460 void CAudioDevice::COutputPort::MopRestartTunnel()
       
   461 	{
       
   462 	}
       
   463 	
       
   464 TUint32 CAudioDevice::COutputPort::MopBufferSize() const
       
   465 	{
       
   466 	return iBufferSize;
       
   467 	}
       
   468 	
       
   469 void CAudioDevice::CInputPort::MipSetObserver(const MMdfInputPortObserver& aObserver)
       
   470 	{
       
   471 	iObserver = const_cast<MMdfInputPortObserver*>(&aObserver);
       
   472 	}
       
   473 
       
   474 void CAudioDevice::COutputPort::MopSetObserver(const MMdfOutputPortObserver& aObserver)
       
   475 	{
       
   476 	iObserver = const_cast<MMdfOutputPortObserver*>(&aObserver);
       
   477 	}
       
   478 
       
   479 TInt CAudioDevice::COutputPort::MopCreateCustomInterface(TUid aUid)
       
   480 	{
       
   481 	if (aUid.iUid == KMmfRecordSettingsCustomInterface)
       
   482 		{
       
   483 		return KErrNone;
       
   484 		}
       
   485 	return KErrNotSupported;	
       
   486 	}
       
   487 	
       
   488 TAny* CAudioDevice::COutputPort::MopCustomInterface(TUid aUid)
       
   489 	{
       
   490 	if (aUid.iUid == KMmfRecordSettingsCustomInterface)
       
   491 		{
       
   492 		return dynamic_cast<MRecordCustomInterface*>(this);
       
   493 		}
       
   494 
       
   495 	return NULL;
       
   496 	}
       
   497 	
       
   498 void CAudioDevice::COutputPort::RunL()
       
   499 	{
       
   500 	if (iCurrentBuffer != NULL)
       
   501 		{
       
   502 		// If we've been signalled with a buffer, callback that we've completed the writing of the
       
   503 		// buffer
       
   504 		if (iObserver)
       
   505 			{		
       
   506 			TInt length = iCurrentBuffer->BufferSize();
       
   507 			iBytesRecorded += length;
       
   508 			if (length<iBufferSize)
       
   509 				{
       
   510 				iCurrentBuffer->SetLastBuffer(ETrue);
       
   511 				iParent.SoundDevice().CancelRecordData(); // Required so that a resume of an encode functions correctly
       
   512 				}
       
   513 					
       
   514 			iObserver->MopoReadDataComplete(this, iCurrentBuffer, iStatus.Int());
       
   515 			
       
   516 			}
       
   517 			iCurrentBuffer = NULL;
       
   518 		}
       
   519 		
       
   520 	if (iStatus == KErrNone)
       
   521 		{
       
   522 		if (iBuffers.Count()>0)
       
   523 			{
       
   524 			iCurrentBuffer = iBuffers[0];
       
   525 			iBuffers.Remove(0);
       
   526 			
       
   527 			if (CMMFBuffer::IsSupportedDataBuffer(iCurrentBuffer->Type()))
       
   528 				{
       
   529 				TDes8& aBufferDes = (static_cast<CMMFDataBuffer*>(iCurrentBuffer))->Data();
       
   530 				iStatus = KRequestPending;
       
   531 				iParent.SoundDevice().RecordData(iStatus, aBufferDes);
       
   532 				SetActive();
       
   533 				}
       
   534 			}
       
   535 		}
       
   536 	}
       
   537 
       
   538 void CAudioDevice::COutputPort::DoCancel()
       
   539 	{
       
   540 	if (iParent.SoundDevice().Handle())
       
   541 		{
       
   542 		iParent.SoundDevice().CancelRecordData();
       
   543 		iParent.SoundDevice().FlushRecordBuffer();
       
   544 		}		
       
   545 	}
       
   546 	
       
   547 TInt CAudioDevice::COutputPort::SampleRate()
       
   548 	{
       
   549 	return iSampleRate;
       
   550 	}
       
   551 	
       
   552 TInt CAudioDevice::COutputPort::Channels()
       
   553 	{
       
   554 	return iChannels;
       
   555 	}
       
   556 
       
   557 CAudioDevice::COutputPort::~COutputPort()
       
   558 	{
       
   559 	Cancel();
       
   560 	iBuffers.Close();
       
   561 	}
       
   562 	
       
   563 // from MRecordCustomInterface
       
   564 void CAudioDevice::COutputPort::SetGain(TUint aGain)
       
   565 	{
       
   566 	iGain = aGain;
       
   567 	}
       
   568 TUint CAudioDevice::COutputPort::Gain()
       
   569 	{
       
   570 	return iGain;
       
   571 	}
       
   572 	
       
   573 TUint CAudioDevice::COutputPort::BytesRecorded()
       
   574 	{
       
   575 	return iBytesRecorded;
       
   576 	}
       
   577 
       
   578 // ------------------------------------------------------------------------------------------
       
   579 // CAudioDevice Implementation
       
   580 
       
   581 
       
   582 CAudioDevice::CAudioDevice()
       
   583 	{
       
   584 	}
       
   585 	
       
   586 CAudioDevice::~CAudioDevice()
       
   587 	{
       
   588 	delete iInputPort;
       
   589 	delete iOutputPort;
       
   590 	iSoundDevice.Close();
       
   591 	}
       
   592 
       
   593 void CAudioDevice::Execute()
       
   594 	{
       
   595 	__ASSERT_ALWAYS(iObserver, User::Panic(KAudioDevicePanic, EObserverNotSet));
       
   596 	TInt err = KErrNone;
       
   597 	if(!iSoundDevice.Handle())
       
   598 		{
       
   599 		err = iSoundDevice.Open();
       
   600 		}
       
   601 	
       
   602 	RMdaDevSound::TCurrentSoundFormatBuf buf;
       
   603 	if (err == KErrNone)
       
   604 		{
       
   605 		if(iState == EProcessingUnitPaused)
       
   606 			{
       
   607 			iSoundDevice.ResumePlaying();
       
   608 			}
       
   609 		else
       
   610 			{
       
   611 			// Set play format (for input port)
       
   612 			iSoundDevice.GetPlayFormat(buf);
       
   613 			buf().iRate = iInputPort->SampleRate();
       
   614 			buf().iChannels = iInputPort->Channels();
       
   615 			buf().iBufferSize = KBufferSize;
       
   616 			buf().iEncoding = RMdaDevSound::EMdaSoundEncoding16BitPCM;
       
   617 			err = iSoundDevice.SetPlayFormat(buf);
       
   618 			}
       
   619 		}
       
   620 	iState = EProcessingUnitExecuting;	
       
   621 	if (err == KErrNone)
       
   622 		{
       
   623 		// Set record format (for output format)
       
   624 		iSoundDevice.GetRecordFormat(buf);
       
   625 		buf().iRate = iOutputPort->SampleRate();
       
   626 		buf().iChannels = iOutputPort->Channels();
       
   627 		buf().iBufferSize = KBufferSize;
       
   628 		buf().iEncoding = RMdaDevSound::EMdaSoundEncoding16BitPCM;
       
   629 		iSoundDevice.SetRecordFormat(buf);
       
   630 		iInputPort->Execute();
       
   631 		iOutputPort->Execute();
       
   632 		}
       
   633 	else 
       
   634 		{
       
   635 		iObserver->ExecuteComplete(this, err);
       
   636 		}		
       
   637 	}
       
   638 
       
   639 TInt CAudioDevice::Pause()
       
   640 	{
       
   641 	iState = EProcessingUnitPaused;
       
   642 	iInputPort->Pause();
       
   643 	iOutputPort->Pause();
       
   644 	return KErrNone;
       
   645 	}
       
   646 
       
   647 void CAudioDevice::Stop()
       
   648 	{
       
   649 	if(iState == EProcessingUnitExecuting || iState == EProcessingUnitPaused)
       
   650 		{
       
   651 		// Cancel and flush the device driver		
       
   652 		iInputPort->Stop();
       
   653 		iOutputPort->Stop();
       
   654 		iState = EProcessingUnitIdle;
       
   655 		
       
   656 		// Close the sound device
       
   657 		iSoundDevice.Close();	
       
   658 		}		
       
   659 	}
       
   660 	
       
   661 CAudioDevice* CAudioDevice::NewL()
       
   662 	{
       
   663 	CAudioDevice* self = new (ELeave) CAudioDevice;
       
   664 	CleanupStack::PushL(self);
       
   665 	self->ConstructL();
       
   666 	CleanupStack::Pop(self);
       
   667 	return self;
       
   668 	}
       
   669 	
       
   670 TInt CAudioDevice::Create(const MMdfProcessingUnitObserver& aObserver)
       
   671 	{
       
   672 	iObserver = const_cast<MMdfProcessingUnitObserver*>(&aObserver);
       
   673 	return KErrNone;
       
   674 	}
       
   675 	
       
   676 TInt CAudioDevice::Configure(const TPuConfig& /*aConfigurationSetup*/)
       
   677 	{
       
   678 	return KErrNotSupported;
       
   679 	}
       
   680 	
       
   681 TInt CAudioDevice::GetConfig(TPuConfig& /*aConfigurationSetup*/)
       
   682 	{
       
   683 	return KErrNotSupported;
       
   684 	}
       
   685 
       
   686 TInt CAudioDevice::GetInputPorts(RPointerArray<MMdfInputPort>& aComponentInputPorts )
       
   687 	{
       
   688 	return aComponentInputPorts.Append(iInputPort);
       
   689 	}
       
   690 
       
   691 TInt CAudioDevice::GetOutputPorts(RPointerArray<MMdfOutputPort>& aComponentOutputPorts )
       
   692 	{
       
   693 	return aComponentOutputPorts.Append(iOutputPort);
       
   694 	}
       
   695 
       
   696 void CAudioDevice::ConstructL()
       
   697 	{
       
   698 	iInputPort = CInputPort::NewL(*this);
       
   699 	iOutputPort = COutputPort::NewL(*this);
       
   700 	iState = EProcessingUnitLoaded;
       
   701 	}
       
   702 
       
   703 void CAudioDevice::Initialize()
       
   704 	{
       
   705 	__ASSERT_ALWAYS(iObserver, User::Panic(KAudioDevicePanic, EObserverNotSet));
       
   706 	
       
   707 	iObserver->InitializeComplete(this, KErrNone);
       
   708 	iState = EProcessingUnitIdle;
       
   709 	}
       
   710 
       
   711 MMdfProcessingUnitObserver* CAudioDevice::Observer()
       
   712 	{
       
   713 	return iObserver;	
       
   714 	}
       
   715 		
       
   716 TProcessingUnitState CAudioDevice::State()
       
   717 	{
       
   718 	return iState;	
       
   719 	}
       
   720 		
       
   721 RMdaDevSound& CAudioDevice::SoundDevice()
       
   722 	{
       
   723 	return iSoundDevice;
       
   724 	}
       
   725 	
       
   726 TAny* CAudioDevice::CustomInterface(TUid /*aUid*/)
       
   727 	{
       
   728 	return NULL;
       
   729 	}
       
   730 		
       
   731 TInt CAudioDevice::CreateCustomInterface(TUid /*aUid*/)
       
   732 	{
       
   733 	return KErrNotSupported;
       
   734 	}
       
   735 
       
   736 // ------------------------------------------------------------------------------------------	
       
   737 // ECOM Implementation table entry	
       
   738 	
       
   739 const TImplementationProxy ImplementationTable[] = 
       
   740 	{
       
   741 	IMPLEMENTATION_PROXY_ENTRY(KUidPUAudioDevice,	CAudioDevice::NewL),
       
   742 	};
       
   743 
       
   744 EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount)
       
   745 	{
       
   746 	aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy);
       
   747 	return ImplementationTable;
       
   748 	}
       
   749