multimediacommscontroller/tsrc/mmfstub/src/MmfAudioOutput_STUB.cpp
changeset 0 1bce908db942
equal deleted inserted replaced
-1:000000000000 0:1bce908db942
       
     1 /*
       
     2 * Copyright (c) 2002-2005 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 
       
    21 #include "MmfAudioOutput.h"
       
    22 #include <ecom/implementationproxy.h>
       
    23 #include <mmf/server/mmfformat.h>
       
    24 
       
    25 #include "mcctestuids.hrh"
       
    26 
       
    27 
       
    28 void Panic(TInt aPanicCode)
       
    29 	{
       
    30 	_LIT(KMMFAudioOutputPanicCategory, "MMFAudioOutput");
       
    31 	User::Panic(KMMFAudioOutputPanicCategory, aPanicCode);
       
    32 	}
       
    33 
       
    34 /**
       
    35 Allocates and constructs a new audio output sink.
       
    36 
       
    37 Static standard SymbianOS 2 phase constuction method.
       
    38 
       
    39 @return A pointer to the new sink.
       
    40 */
       
    41 MDataSink* CMMFAudioOutput::NewSinkL()
       
    42 	{
       
    43 	CMMFAudioOutput* self = new (ELeave) CMMFAudioOutput ;
       
    44 	CleanupStack::PushL(self);
       
    45 	self->ConstructL();
       
    46 	CleanupStack::Pop();
       
    47 	return static_cast<MDataSink*>( self ); 
       
    48 	}
       
    49 
       
    50 /**
       
    51 Standard SymbianOS ConstructL.
       
    52 
       
    53 Used to initialise member varibles with device specific behaviour.
       
    54 */
       
    55 void CMMFAudioOutput::ConstructL()
       
    56 	{
       
    57 	iInitializeState = KErrNone;
       
    58 	iDataTypeCode = KMMFFourCCCodePCM16;
       
    59 	iNeedsSWConversion = EFalse;
       
    60 	iSourceSampleRate = 0;
       
    61 	}
       
    62 
       
    63 /**
       
    64 Overridable constuction specific to this datasource.
       
    65 
       
    66 The default implementation does nothing.
       
    67 
       
    68 @param  aInitData
       
    69         The initialisation data.
       
    70 */
       
    71 void CMMFAudioOutput::ConstructSinkL( const TDesC8& /*aInitData*/ )
       
    72 	{
       
    73 	}
       
    74 
       
    75 
       
    76 /**
       
    77 @deprecated
       
    78 
       
    79 Gets audio from hardware device abstracted MMFDevsound (not used).
       
    80 
       
    81 @param  aBuffer
       
    82         The data to write out to a Hardware Device.
       
    83 @param  aSupplier
       
    84         The MDataSource consuming the data contained in aBuffer
       
    85 */
       
    86 void CMMFAudioOutput::HWEmptyBufferL(CMMFBuffer* /*aBuffer*/, MDataSource* /*aSupplier*/)
       
    87 	{
       
    88 	}
       
    89 
       
    90 /**
       
    91 Sends audio to MMFDevsound.
       
    92 
       
    93 @param  aBuffer
       
    94         The data to write out.
       
    95 @param  aSupplier
       
    96         The search criteria for the supplier.
       
    97 @param  aMediaId
       
    98         The type of data supplied - currently ignored.
       
    99 */
       
   100 void CMMFAudioOutput::EmptyBufferL(CMMFBuffer* aBuffer, MDataSource* aSupplier, TMediaId /*aMediaId*/)
       
   101 	{
       
   102 	iSupplier = aSupplier;
       
   103 
       
   104 	if (!iMMFDevSound)
       
   105 		Panic(EMMFAudioOutputDevSoundNotLoaded);
       
   106 
       
   107 	if ((aBuffer != NULL) && (!CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type())))
       
   108 		User::Leave(KErrNotSupported);
       
   109 
       
   110 	if (aSupplier == NULL)
       
   111 		User::Leave(KErrArgument);
       
   112 	}
       
   113 
       
   114 
       
   115 
       
   116 /**
       
   117 Negotiates with the source to set, for example, the sample rate and number of channels.
       
   118 
       
   119 Called if the sink's setup depends on source.
       
   120 
       
   121 @param  aSource
       
   122         The data source with which to negotiate.
       
   123 */
       
   124 void CMMFAudioOutput::NegotiateL(MDataSource& aSource)
       
   125 	{
       
   126 	if (aSource.DataSourceType() == KUidMmfFormatDecode)
       
   127 		{//source is a clip so for now set sink settings to match source
       
   128 		iSourceSampleRate = ((CMMFFormatDecode&)aSource).SampleRate();
       
   129 		iSourceChannels = ((CMMFFormatDecode&)aSource).NumChannels(); 
       
   130 		iSourceFourCC.Set(aSource.SourceDataTypeCode(TMediaId(KUidMediaTypeAudio)));
       
   131 	
       
   132 		((CMMFFormatDecode&)aSource).SuggestSourceBufferSize(KAudioOutputDefaultFrameSize);
       
   133 		}
       
   134 		
       
   135 	// Query DevSound capabilities and Try to use DevSound sample rate and 
       
   136 	// mono/stereo capability
       
   137 	if (!iMMFDevSound)
       
   138 		Panic(EMMFAudioOutputDevSoundNotLoaded);
       
   139 
       
   140 	TMMFState prioritySettingsState = iPrioritySettings.iState; //should be EMMFStatePlaying
       
   141 	//to use the GetSupportedInputDatatypes but we'll save it just in case it's not
       
   142 	iPrioritySettings.iState = EMMFStatePlaying; //if playing does not support any output data types
       
   143 	iPrioritySettings.iState = prioritySettingsState;
       
   144 	
       
   145 	iDataTypeCode = KMMFFourCCCodePCM16;	
       
   146 	}
       
   147 
       
   148 /**
       
   149 Sets the sink's priority settings.
       
   150 
       
   151 @param  aPrioritySettings
       
   152         The sink's priority settings. Takes enumerations to determine audio playback priority. 
       
   153         Higher numbers mean high priority (can interrupt lower priorities).
       
   154 */
       
   155 void CMMFAudioOutput::SetSinkPrioritySettings(const TMMFPrioritySettings& aPrioritySettings)
       
   156 	{
       
   157 	iPrioritySettings = aPrioritySettings;
       
   158 	if (!iMMFDevSound)
       
   159 		Panic(EMMFAudioOutputDevSoundNotLoaded);
       
   160 	}
       
   161 
       
   162 /**
       
   163 Gets the sink's data type code.
       
   164 
       
   165 Used by datapath MDataSource / MDataSink for codec matching.
       
   166 
       
   167 @param  aMediaId
       
   168         The Media ID. Optional parameter to specifiy specific stream when datasource contains more
       
   169         than one stream of data.
       
   170 
       
   171 @return	The 4CC of the data expected by this sink.
       
   172 */
       
   173 TFourCC CMMFAudioOutput::SinkDataTypeCode(TMediaId /*aMediaId*/)
       
   174 	{
       
   175 	return iDataTypeCode;
       
   176 	}
       
   177 
       
   178 /**
       
   179 Sets the sink's data type code.
       
   180 
       
   181 @param  aSinkFourCC
       
   182         The 4CC of the data to be supplied to this sink.
       
   183 @param  aMediaId
       
   184         The Media ID. Optional parameter to specifiy specific stream when datasource contains more 
       
   185         than one stream of data.
       
   186 
       
   187 @return An error code indicating if the function call was successful. KErrNone on success, otherwise
       
   188         another of the system-wide error codes.
       
   189 */
       
   190 TInt CMMFAudioOutput::SetSinkDataTypeCode(TFourCC aSinkFourCC, TMediaId /*aMediaId*/)
       
   191 	{//will check with devsound to see if aSinkFourCC is supported
       
   192 	 //when this is added to devsound
       
   193 	iDataTypeCode = aSinkFourCC;
       
   194 	return KErrNone;
       
   195 	}
       
   196 
       
   197 /**
       
   198 Prime's the sink.
       
   199 
       
   200 This is a virtual function that each derived class must implement, but may be left blank for default 
       
   201 behaviour.
       
   202 
       
   203 Called by CMMFDataPath::PrimeL().
       
   204 */
       
   205 void CMMFAudioOutput::SinkPrimeL()
       
   206 	{
       
   207 	iFirstBufferSent = EFalse;
       
   208 	if (iState == EIdle)
       
   209 		{
       
   210 		if (!iMMFDevSound) User::Leave(KErrNotReady);
       
   211 		iState = EDevSoundReady;
       
   212 		}
       
   213 	}
       
   214 
       
   215 /**
       
   216 Pauses the sink.
       
   217 
       
   218 This is a virtual function that each derived class must implement, but may be left blank for default 
       
   219 behaviour.
       
   220 */
       
   221 void CMMFAudioOutput::SinkPauseL()
       
   222 	{
       
   223 	if (!iMMFDevSound)
       
   224 		Panic(EMMFAudioOutputDevSoundNotLoaded);
       
   225 	else
       
   226 		iMMFDevSound->Pause();
       
   227 	iFirstBufferSent = EFalse;
       
   228 	iState = EPaused;
       
   229 	}
       
   230 
       
   231 /**
       
   232 Starts playing the sink.
       
   233 
       
   234 This is a virtual function that each derived class must implement, but may be left blank for default
       
   235 behaviour.
       
   236 */
       
   237 void CMMFAudioOutput::SinkPlayL()
       
   238 	{
       
   239 	if (iState == EPaused)
       
   240 		{
       
   241 		// DevSound remains initialised when paused
       
   242 		return;
       
   243 		}
       
   244 	iState = EDevSoundReady;
       
   245 	}
       
   246 
       
   247 /**
       
   248 Stops the sink.
       
   249 
       
   250 This is a virtual function that each derived class must implement, but may be left blank for default
       
   251 behaviour.
       
   252 */
       
   253 void CMMFAudioOutput::SinkStopL()
       
   254 	{
       
   255 	if (iState == EDevSoundReady)
       
   256 		{//not waiting on a buffer being played so stop devsound now
       
   257 		iState = EIdle;
       
   258 		if (iFirstBufferSent)
       
   259 			{
       
   260 			if (!iMMFDevSound)
       
   261 				{
       
   262 				Panic(EMMFAudioOutputDevSoundNotLoaded);
       
   263 				}
       
   264 			else
       
   265 				{
       
   266 				iFirstBufferSent = EFalse;
       
   267 				iMMFDevSound->Stop();
       
   268 				}
       
   269 			}
       
   270 		}
       
   271 	else if (iState == EPaused)	//DEF46250 need to handle pause separately as we should always stop regardless of the state of iFirstBufferSent
       
   272 		{
       
   273 		iFirstBufferSent = EFalse;
       
   274 		iMMFDevSound->Stop();
       
   275 		iState = EIdle; 
       
   276 		}
       
   277 	} 
       
   278 
       
   279 /**
       
   280 Returns the playback state (EStopped, EPlaying, EPaused etc) of this sink
       
   281 */
       
   282 TInt CMMFAudioOutput::State()
       
   283 	{
       
   284 	return iState;
       
   285 	}
       
   286 
       
   287 /**
       
   288 Logs on the sink's thread.
       
   289 
       
   290 Thread specific initialization procedure for this device. Runs automatically on thread construction.
       
   291 
       
   292 @param  aEventHandler
       
   293         The event handler.
       
   294 
       
   295 @return An error code indicating if the function call was successful. KErrNone on success, otherwise
       
   296         another of the system-wide error codes.
       
   297 */
       
   298 TInt CMMFAudioOutput::SinkThreadLogon(MAsyncEventHandler& aEventHandler)
       
   299 	{
       
   300 	iEventHandler = &aEventHandler;
       
   301 	TInt err = KErrNone;
       
   302 	if (!iDevSoundLoaded)
       
   303 		TRAP(err, LoadL());
       
   304 	return err;
       
   305 	}
       
   306 
       
   307 /**
       
   308 Logs off the sink thread.
       
   309 
       
   310 Thread specific destruction procedure for this device. Runs automatically on thread destruction.
       
   311 */
       
   312 void CMMFAudioOutput::SinkThreadLogoff()
       
   313 	{
       
   314 	if(iMMFDevSound)
       
   315 		{
       
   316 		iMMFDevSound->Stop();
       
   317 		delete iMMFDevSound;
       
   318 		iMMFDevSound = NULL;
       
   319 		}
       
   320 	iDevSoundLoaded = EFalse;
       
   321 	iState = EIdle;
       
   322 	}
       
   323 
       
   324 /**
       
   325 Called by MDataSource to pass back a full buffer to the sink. 
       
   326 
       
   327 Should never be called by a sink, as sinks empty buffers, not fill them.
       
   328 
       
   329 @param  aBuffer
       
   330         The filled buffer.
       
   331 */
       
   332 void CMMFAudioOutput::BufferFilledL(CMMFBuffer* /*aBuffer*/)
       
   333 	{
       
   334 	Panic(EMMFAudioOutputPanicBufferFilledLNotSupported);
       
   335 	}
       
   336 
       
   337 /**
       
   338 Tests whether a sink buffer can be created.
       
   339 
       
   340 The default implementation returns true.
       
   341 
       
   342 @return A boolean indicating if the sink buffer can be created. ETrue if it can, otherwise EFalse.
       
   343 */
       
   344 TBool CMMFAudioOutput::CanCreateSinkBuffer()
       
   345 	{
       
   346 	return ETrue;
       
   347 	}
       
   348 
       
   349 /**
       
   350 Creates a sink buffer.
       
   351 
       
   352 Intended for asynchronous usage (buffers supplied by Devsound device)
       
   353 
       
   354 @param  aMediaId
       
   355         The Media ID.
       
   356 @param	aReference
       
   357 		A boolean indicating if MDataSink owns the buffer. ETrue if does, otherwise EFalse.
       
   358 
       
   359 @return A sink buffer.
       
   360 */
       
   361 CMMFBuffer* CMMFAudioOutput::CreateSinkBufferL(TMediaId /*aMediaId*/, TBool &aReference)
       
   362 	{
       
   363 	//iDevSoundBuffer = CMMFDataBuffer::NewL(KAudioOutputDefaultFrameSize);
       
   364 	iDevSoundBuffer = NULL;		//DevSound supplies this buffer in first callback
       
   365 	aReference = ETrue;
       
   366 	if ( iNeedsSWConversion )
       
   367 		return iConvertBuffer;
       
   368 	else
       
   369 		return iDevSoundBuffer;
       
   370 	}
       
   371 
       
   372 /**
       
   373 Standard SymbianOS destructor.
       
   374 */
       
   375 CMMFAudioOutput::~CMMFAudioOutput()
       
   376 	{
       
   377 	// The following will never have been allocated unless
       
   378 	// software conversion was required, and due to certain DevSound
       
   379 	// implementations, this requirement can change dynamically.
       
   380 	delete iChannelAndSampleRateConverterFactory;
       
   381 	delete iConvertBuffer;
       
   382 
       
   383 	if (iMMFDevSound)
       
   384 		{
       
   385 		iMMFDevSound->Stop();
       
   386 		
       
   387 		}
       
   388     delete iMMFDevSound;
       
   389     iMMFDevSound = NULL;
       
   390 	}
       
   391 
       
   392 void CMMFAudioOutput::ConfigDevSoundL()
       
   393 	{
       
   394 	iMMFDevSound->SetConfigL(iDevSoundConfig);
       
   395 	}
       
   396 
       
   397 
       
   398 /**
       
   399 @deprecated
       
   400 
       
   401 This method should not be used - it is provided to maintain SC with v7.0s.
       
   402 
       
   403 @param  aAudioType
       
   404         The 4CC of the data supplied by this source.
       
   405 */
       
   406 void CMMFAudioOutput::SetDataTypeL(TFourCC aAudioType)
       
   407 	{
       
   408 	if (aAudioType != KMMFFourCCCodePCM16)
       
   409 		{
       
   410 		User::Leave(KErrNotSupported);
       
   411 		}
       
   412 	}
       
   413 
       
   414 
       
   415 /**
       
   416 @deprecated
       
   417 
       
   418 This method should not be used - it is provided to maintain SC with v7.0s.
       
   419 
       
   420 @return The 4CC of the data supplied by this source.
       
   421 */
       
   422 TFourCC CMMFAudioOutput::DataType() const
       
   423 	{
       
   424 	return KMMFFourCCCodePCM16;
       
   425 	}
       
   426 
       
   427 
       
   428 /**
       
   429 Loads audio device drivers and initialise this device.
       
   430 */
       
   431 void CMMFAudioOutput::LoadL()
       
   432 	{
       
   433 	if ( iMMFDevSound )
       
   434 	    {
       
   435 	    iDevSoundLoaded = ETrue;
       
   436 	    return;
       
   437 	    }
       
   438 	    
       
   439 	iFirstBufferSent = EFalse;
       
   440 	if (iState != EDevSoundReady)
       
   441 		iState = EIdle;
       
   442 	
       
   443 	iMMFDevSound = CMMFDevSound::NewL();
       
   444 
       
   445 	//This is done to maintain compatibility with the media server
       
   446 	iMMFDevSound->SetVolume(iMMFDevSound->MaxVolume() - 1);
       
   447 
       
   448 	//note cannot perform further initlaisation here untill the datatype is known
       
   449 
       
   450 	iDevSoundLoaded = ETrue;
       
   451 	}
       
   452 
       
   453 /**
       
   454 DeviceMessage MMFDevSoundObserver
       
   455 */
       
   456 void CMMFAudioOutput::DeviceMessage(TUid /*aMessageType*/, const TDesC8& /*aMsg*/)
       
   457 	{
       
   458 	}
       
   459 
       
   460 
       
   461 /**
       
   462 ToneFinished MMFDevSoundObserver called when a tone has finished or interrupted
       
   463 
       
   464 Should never get called.
       
   465 */
       
   466 void CMMFAudioOutput::ToneFinished(TInt /*aError*/)
       
   467 	{
       
   468 	//we should never get a tone error in MMFAudioOutput!
       
   469 	__ASSERT_DEBUG(EFalse, Panic(EMMFAudioOutputPanicToneFinishedNotSupported));
       
   470 	}
       
   471 
       
   472 
       
   473 /**
       
   474 RecordError MMFDevSoundObserver called when recording has halted.
       
   475 
       
   476 Should never get called.
       
   477 */
       
   478 void CMMFAudioOutput::RecordError(TInt /*aError*/)
       
   479 	{
       
   480 	//we should never get a recording error in MMFAudioOutput!
       
   481 	__ASSERT_DEBUG(EFalse, Panic(EMMFAudioOutputPanicRecordErrorNotSupported));
       
   482 	}
       
   483 
       
   484 /**
       
   485 InitializeComplete MMFDevSoundObserver called when devsound initialisation completed.
       
   486 */
       
   487 void CMMFAudioOutput::InitializeComplete(TInt aError)
       
   488 	{
       
   489 	
       
   490 	if (aError == KErrNone)
       
   491 		{
       
   492 		iState = EDevSoundReady;
       
   493 		}
       
   494 	
       
   495 	if(iInitializeState == KRequestPending)
       
   496 		{
       
   497 		iInitializeState = aError;
       
   498 		iActiveSchedulerWait->AsyncStop();
       
   499 		}
       
   500 	}
       
   501 
       
   502 /**
       
   503 BufferToBeEmptied MMFDevSoundObserver - should never get called.
       
   504 */
       
   505 void CMMFAudioOutput::BufferToBeEmptied(CMMFBuffer* /*aBuffer*/)
       
   506 	{
       
   507 	__ASSERT_DEBUG(EFalse, Panic(EMMFAudioOutputPanicRecordErrorNotSupported));
       
   508 	}
       
   509 
       
   510 /**
       
   511 BufferToBeFilled MMFDevSoundObserver.
       
   512 Called when buffer used up.
       
   513 */
       
   514 void CMMFAudioOutput::BufferToBeFilled(CMMFBuffer* aBuffer)
       
   515 	{
       
   516 	TInt err = KErrNone;
       
   517 
       
   518 	TRAP(err, iSupplier->BufferEmptiedL(aBuffer));
       
   519 
       
   520 	//This error needs handling properly
       
   521 	__ASSERT_DEBUG(!err, Panic(err));
       
   522 	}
       
   523 
       
   524 /**
       
   525 PlayError MMFDevSoundObserver.
       
   526 
       
   527 Called when stopped due to error or EOF.
       
   528 */
       
   529 void CMMFAudioOutput::PlayError(TInt aError)
       
   530 	{
       
   531 	iMMFDevsoundError = aError;
       
   532 
       
   533 	//send EOF to client
       
   534 	TMMFEvent event(KMMFEventCategoryPlaybackComplete, aError);
       
   535 	SendEventToClient(event);
       
   536 
       
   537 	//stop stack overflow / looping problem - AD
       
   538 	if (aError == KErrCancel)
       
   539 		return;
       
   540 
       
   541 	// NB KErrInUse, KErrDied OR KErrAccessDenied may be returned by the policy server
       
   542 	// to indicate that the sound device is in use by another higher priority client.
       
   543 	if (aError == KErrInUse || aError == KErrDied || aError == KErrAccessDenied)
       
   544 		return;
       
   545 
       
   546 	if (iState == EIdle)
       
   547 		{//probably have stopped audio output and have got an underflow from last buffer
       
   548 		iMMFDevSound->Stop();
       
   549 		iFirstBufferSent = EFalse;
       
   550 		}
       
   551 	}
       
   552 
       
   553 
       
   554 /**
       
   555 ConvertError MMFDevSoundObserver.
       
   556 
       
   557 Should never get called.
       
   558 */
       
   559 void CMMFAudioOutput::ConvertError(TInt /*aError*/)
       
   560 	{
       
   561 	}
       
   562 
       
   563 
       
   564 /**
       
   565 Returns the number of bytes played.
       
   566 
       
   567 @return	The number of bytes played. If 16-bit divide this number returned by 2 to get word length.
       
   568 */
       
   569 TInt CMMFAudioOutput::BytesPlayed()
       
   570 	{
       
   571 	if (!iMMFDevSound)
       
   572 		Panic(EMMFAudioOutputDevSoundNotLoaded);
       
   573 	return iMMFDevSound->SamplesPlayed();
       
   574 	}
       
   575 
       
   576 /**
       
   577 Returns the sound device.
       
   578 
       
   579 Accessor function exposing public CMMFDevsound methods.
       
   580 
       
   581 @return	A reference to a CMMFDevSound objector.
       
   582 */
       
   583 CMMFDevSound& CMMFAudioOutput::SoundDevice()
       
   584 	{
       
   585 	if (!iMMFDevSound)
       
   586 		Panic(EMMFAudioOutputDevSoundNotLoaded);
       
   587 	return *iMMFDevSound;
       
   588 	}
       
   589 
       
   590 void CMMFAudioOutput::SendEventToClient(const TMMFEvent& aEvent)
       
   591 	{
       
   592 	iEventHandler->SendEventToClient(aEvent);
       
   593 	}
       
   594 // __________________________________________________________________________
       
   595 // Exported proxy for instantiation method resolution
       
   596 // Define the interface UIDs
       
   597 
       
   598 
       
   599 
       
   600 const TImplementationProxy ImplementationTable[] =
       
   601 	{
       
   602 		IMPLEMENTATION_PROXY_ENTRY(KMccUidAudioOutputInterface,	CMMFAudioOutput::NewSinkL)
       
   603 	};
       
   604 
       
   605 EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount)
       
   606 	{
       
   607 	aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy);
       
   608 
       
   609 	return ImplementationTable;
       
   610 	}
       
   611