camcordermmfplugin/mediarecorder/Src/CCMRAudioRecorder.cpp
changeset 0 9b3e960ffc8a
child 10 6bc4220d7f67
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/camcordermmfplugin/mediarecorder/Src/CCMRAudioRecorder.cpp	Thu Dec 17 08:51:24 2009 +0200
@@ -0,0 +1,709 @@
+/*
+* Copyright (c) 2004 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Audio recorder class. Client side for audio thread
+*
+*/
+
+
+// INCLUDE FILES
+
+#include    "CCMRAudioRecorder.h"
+#include    "CCMRSupportedCodecs.h"
+#include    "CCMRAudioCodecs.h"
+#include    "CCMRAudioCodecData.h"
+#include    "CCMRActiveOutput.h"
+#include    "CCMRVideoHWParams.h"
+
+#include    <mmf/server/mmfdatabuffer.h>
+#include    <mmf/server/mmfaudioinput.h>
+#include 	<AudioPreference.h>                // For MMF audio preference definitions.
+
+// MACROS
+
+// Assertion macro wrapper for code cleanup
+#define ARASSERT(x) __ASSERT_DEBUG(x, User::Panic(_L("CCMRAUDIORECORDER"), EInternalAssertionFailure)) 
+
+// Debug print macro
+#ifdef _DEBUG
+#include <e32svr.h>
+#define PRINT(x) RDebug::Print x
+#else
+#define PRINT(x)
+#endif
+
+
+
+
+// ================= MEMBER FUNCTIONS =======================
+
+// -----------------------------------------------------------------------------
+// CCMRAudioRecorder::CCMRAudioRecorder
+//
+// Default constructor.
+// -----------------------------------------------------------------------------
+//
+CCMRAudioRecorder::CCMRAudioRecorder()
+    {
+    iObserver = NULL;
+    iDataSource = NULL;
+    iThreadCreated = EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioRecorder::~CCMRAudioRecorder
+//
+// Destructor.
+// -----------------------------------------------------------------------------
+//
+CCMRAudioRecorder::~CCMRAudioRecorder()
+    {
+    PRINT((_L("CCMRAudioRecorder::~CCMRAudioRecorder() in")));
+    
+    delete iThreadEventMonitor;
+    iThreadEventMonitor = NULL;
+
+    if ( iThreadCreated )
+        {
+        iThreadProxy.Close();
+        }
+    //audio thread already logs off audio source (=> deletes it)
+    PRINT((_L("CCMRAudioRecorder::~CCMRAudioRecorder() thread closed")));
+
+    iObserver = NULL;
+    iDataSource = NULL;
+    iOutputAO = NULL;
+    
+    delete iAudioCodecs;
+    iAudioCodecs = NULL;
+
+    PRINT((_L("CCMRAudioRecorder::~CCMRAudioRecorder() out")));
+    }
+
+
+// -----------------------------------------------------------------------------
+// CCMRAudioRecorder::NewL
+//
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CCMRAudioRecorder* CCMRAudioRecorder::NewL()
+    {
+    
+    CCMRAudioRecorder* self = new (ELeave) CCMRAudioRecorder;
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop();
+    return self;
+    
+    }
+
+
+// -----------------------------------------------------------------------------
+// CCMRAudioRecorder::ConstructL
+//
+// Symbian 2nd phase constructor.
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioRecorder::ConstructL()
+    {
+    SetState(EStateNone);
+    iPrioritySettings.iPriority = KAudioPriorityVideoRecording;
+    iPrioritySettings.iPref =  TMdaPriorityPreference( KAudioPrefVideoRecording );
+
+    RArray<TFourCC> audioTypes;
+    CleanupClosePushL( audioTypes );
+    audioTypes.Reset();
+    
+    iAudioCodecs = CCMRAudioCodecs::NewL();
+    iAudioCodecs->GetSupportedAudioCodecsL( audioTypes );
+    // audioTypes have always >= 1 element now
+    if ( audioTypes.Count() > 0 )
+        {
+        iAudioCodecFourCC = TFourCC(audioTypes[0]);
+        iAudioCodecs->SetAudioCodecL( iAudioCodecFourCC );
+        CCMRRecorderBase::SetTargetBitRateL( iAudioCodecs->GetCodecDataL()->GetBitRateL() );
+        }
+    else
+        {
+        // no audio codecs exist. Must anyway create audio recorder, since mediarecorder should work also video-only and codec support is checked later
+        iAudioCodecFourCC = TFourCC(' ',' ',' ',' ');
+        }
+
+    CleanupStack::PopAndDestroy( &audioTypes ); // calls also audioTypes.Close()
+    }
+
+
+// -----------------------------------------------------------------------------
+// CCMRAudioRecorder::OpenL
+//
+// Open recorder. This is like audio controller's AddSource
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioRecorder::OpenL(MCMRAudioRecorderObserver *aObserver, MDataSource *aSource, 
+                              CCMRActiveOutput* aOutputAO, const TFourCC& aAudioType, CCMRConfigManager* aConfig )
+    {
+    PRINT((_L("CCMRAudioRecorder::OpenL() in")));
+    if ( State() != EStateNone ) 
+        {
+        PRINT((_L("CCMRAudioRecorder::OpenL() already exists")));
+        User::Leave( KErrAlreadyExists );
+        }
+  
+    // save the references/pointers
+    iObserver = aObserver;
+    iConfig = aConfig;
+    iConfig->SetAudioCodec( iAudioCodecFourCC );
+
+    // check the source type
+    if ( aSource && aSource->DataSourceType() != KUidMmfAudioInput)
+        {
+        PRINT((_L("CCMRAudioRecorder::OpenL() unsupported source")));
+        User::Leave(KErrNotSupported);
+        }
+    iDataSource = aSource;
+
+    iOutputAO = aOutputAO;
+
+    // create thread for audio 
+    User::LeaveIfError(iThreadProxy.CreateSubThread(iThreadCreated));
+    User::LeaveIfError(iThreadProxy.SetOutput(iOutputAO));
+
+    iThreadEventMonitor = CCMRSubThreadEventMonitor::NewL(*this, iThreadProxy); 
+    iThreadEventMonitor->Start();
+
+    // add data source => we will be connected also to DevSound and then we can use e.g. gain settings
+    if (iDataSource)
+        {
+        User::LeaveIfError(iThreadProxy.AddDataSource(iDataSource));
+        }
+
+    // set config manager to thread
+    User::LeaveIfError(iThreadProxy.SetConfigManager( aConfig ));
+
+    // SetAudioCodec requires we are at least open
+    SetState( EStateOpen );
+    iObserver->MaroStateChange( State() );
+
+    SetAudioCodecL( aAudioType );
+  
+    PRINT((_L("CCMRAudioRecorder::OpenL() out")));
+    }
+
+
+// -----------------------------------------------------------------------------
+// CCMRAudioRecorder::SetAudioCodecL
+//
+// Set audio codec to be used (overrides the one given in OpenL)
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioRecorder::SetAudioCodecL( const TFourCC& aAudioType )
+    {
+    PRINT((_L("CCMRAudioRecorder::SetAudioCodecL() in")));    
+    if ( ( State() != EStateOpen ) && ( State() != EStateReadyToRecord ) )
+        {
+        PRINT((_L("CCMRAudioRecorder::SetAudioCodecL() wrong state")));
+        User::Leave(KErrNotReady);
+        }
+    if ( aAudioType != iAudioCodecFourCC )
+        {
+        iAudioCodecs->SetAudioCodecL( aAudioType );
+        iAudioCodecFourCC = aAudioType;
+        iConfig->SetAudioCodec(iAudioCodecFourCC);
+
+        SetState( EStateOpen );
+        iObserver->MaroStateChange( State() );
+        }
+    PRINT((_L("CCMRAudioRecorder::SetAudioCodecL() out")));        
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioRecorder::GetAudioCodecL
+// Get the used audio codec.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioRecorder::GetAudioCodecL( TFourCC& aAudioType ) const
+    {
+    if ( (State() == EStateNone) || (iAudioCodecs->GetCodecDataL() == NULL) )
+        {
+        PRINT((_L("CCMRAudioRecorder::GetAudioCodecL() wrong state")));
+        User::Leave(KErrNotReady);
+        }
+
+    aAudioType = iAudioCodecs->GetCodecDataL()->GetCodecFourCCL();
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioRecorder::GetSupportedAudioCodecsL
+// Get the supported & installed audio codecs.
+// This can be called also when the recorder is not open
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioRecorder::GetSupportedAudioCodecsL( RArray<TFourCC>& aAudioTypes ) const
+    {
+    aAudioTypes.Reset();
+    
+    iAudioCodecs->GetSupportedAudioCodecsL( aAudioTypes );
+
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioRecorder::SetPriorityL
+//
+// Set audio priority (for DevSound)
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioRecorder::SetPriorityL(const TMMFPrioritySettings& aPrioritySettings)
+    {
+    if ( State() == EStateNone || State() == EStateRecording || State() == EStatePaused )
+        {
+        PRINT((_L("CCMRAudioRecorder::SetPriorityL() wrong state")));
+        User::Leave(KErrNotReady);
+        }
+    if ( aPrioritySettings.iPriority < EMdaPriorityMin || aPrioritySettings.iPriority > EMdaPriorityMax )
+        {
+        // outside allowed range
+        PRINT((_L("CCMRAudioRecorder::SetPriorityL() unsupported priority")));
+        User::Leave( KErrArgument );
+        }
+
+    iPrioritySettings = aPrioritySettings;
+    SetState( EStateOpen );
+    iObserver->MaroStateChange( State() );
+
+    }
+
+
+// -----------------------------------------------------------------------------
+// CCMRAudioRecorder::SetTargetBitRateL
+//
+// Set audio bitrate. Note: checked only in PrepareL
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioRecorder::SetTargetBitRateL(TInt aBitRate)
+    {
+    PRINT((_L("CCMRAudioRecorder::SetTargetBitRateL() in")));
+    if ( (( State() != EStateOpen ) && ( State() != EStateReadyToRecord )) || (iAudioCodecs->GetCodecDataL() == NULL) )
+        {
+        PRINT((_L("CCMRAudioRecorder::SetTargetBitRateL() wrong state")));
+        User::Leave(KErrNotReady);
+        }
+
+    iAudioCodecs->GetCodecDataL()->SetBitRateL( aBitRate );
+    // if we are here, the bitrate was ok, store it also here since the system assumes recorder class stores it
+    CCMRRecorderBase::SetTargetBitRateL( aBitRate );
+
+    SetState( EStateOpen );
+    iObserver->MaroStateChange( State() );
+    PRINT((_L("CCMRAudioRecorder::SetTargetBitRateL() out")));
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioRecorder::SetTargetSampleRateL
+//
+// Set audio samplerate. AAC only.
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioRecorder::SetTargetSampleRateL(TInt aSampleRate)
+    {
+    PRINT((_L("CCMRAudioRecorder::SetTargetSampleRateL() in, samplerate=%d"),aSampleRate));
+    if ( (( State() != EStateOpen ) && ( State() != EStateReadyToRecord )) || (iAudioCodecs->GetCodecDataL() == NULL) )
+        {
+        PRINT((_L("CCMRAudioRecorder::SetTargetSampleRateL() wrong state")));
+        User::Leave(KErrNotReady);
+        }
+
+    iAudioCodecs->GetCodecDataL()->SetSampleRateL( aSampleRate );
+
+    SetState( EStateOpen );
+    iObserver->MaroStateChange( State() );
+    PRINT((_L("CCMRAudioRecorder::SetTargetSampleRateL() out")));
+    }    
+
+// -----------------------------------------------------------------------------
+// CCMRAudioRecorder::SetChannelModeL
+//
+// Set audio channel mode. AAC only.
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioRecorder::SetChannelModeL(TInt aChannelMode)
+    {
+    PRINT((_L("CCMRAudioRecorder::SetChannelModeL() in, channelmode=%d"), aChannelMode));
+    if ( (( State() != EStateOpen ) && ( State() != EStateReadyToRecord )) || (iAudioCodecs->GetCodecDataL() == NULL) )
+        {
+        PRINT((_L("CCMRAudioRecorder::SetChannelModeL() wrong state")));
+        User::Leave(KErrNotReady);
+        }
+
+    iAudioCodecs->GetCodecDataL()->SetChannelModeL( aChannelMode );
+
+    SetState( EStateOpen );
+    iObserver->MaroStateChange( State() );
+    PRINT((_L("CCMRAudioRecorder::SetChannelModeL() out")));
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioRecorder::MaxGainL
+//
+// Get maximum gain from audio input
+// -----------------------------------------------------------------------------
+//
+TInt CCMRAudioRecorder::MaxGainL()
+    {
+    PRINT((_L("CCMRAudioRecorder::MaxGainL() in")));
+    if ( State() == EStateNone )
+        {
+        PRINT((_L("CCMRAudioRecorder::MaxGainL() wrong state")));
+        User::Leave( KErrNotReady );
+        }
+
+    // check max gain from sound device
+    TInt gain;
+    User::LeaveIfError( iThreadProxy.MaxGain( gain ));
+    PRINT((_L("CCMRAudioRecorder::MaxGainL() almost out, max gain %d"),gain));
+    return gain;
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioRecorder::GainL
+//
+// Get current gain from audio input
+// -----------------------------------------------------------------------------
+//
+TInt CCMRAudioRecorder::GainL()
+    {
+    PRINT((_L("CCMRAudioRecorder::GainL() in")));
+    if ( State() == EStateNone )
+        {
+        PRINT((_L("CCMRAudioRecorder::GainL() wrong state")));
+        User::Leave( KErrNotReady );
+        }
+
+    // check current gain from sound device
+    TInt gain;
+    User::LeaveIfError( iThreadProxy.GetGain( gain ));
+    PRINT((_L("CCMRAudioRecorder::GainL() almost out, gain %d"),gain));
+    return gain;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CCMRAudioRecorder::SetGainL
+//
+// Sets gain for audio input. Can be done before and during recording 
+// and is effective immediately
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioRecorder::SetGainL(TInt aGain)
+    {
+    PRINT((_L("CCMRAudioRecorder::SetGainL() in")));
+    if ( State() == EStateNone )
+        {
+        PRINT((_L("CCMRAudioRecorder::SetGainL() wrong state")));
+        User::Leave( KErrNotReady );
+        }
+    if ( aGain >= 0 ) 
+        {
+        User::LeaveIfError( iThreadProxy.SetGain(aGain));
+
+        PRINT((_L("CCMRAudioRecorder::SetGainL() out")));
+        }
+    else
+        {
+        PRINT((_L("CCMRAudioRecorder::SetGainL() out due to illegal argument: %d"),aGain));
+        User::Leave( KErrArgument );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioRecorder::GetThreadPriority
+//
+// Get audio thread priority
+// -----------------------------------------------------------------------------
+//
+TThreadPriority CCMRAudioRecorder::GetThreadPriority() const
+    {
+    return iThreadProxy.GetThreadPriority();
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioRecorder::PrepareL
+//
+// Prepare recorder for recording (freeze settings / implements PrimeL)
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioRecorder::PrepareL()
+    {
+    PRINT((_L("CCMRAudioRecorder::PrepareL() in    ")));
+
+    if ( (State() != EStateOpen) && (State() != EStateReadyToRecord) )
+        {
+        PRINT((_L("CCMRAudioRecorder::PrepareL() wrong state")));
+        User::Leave( KErrNotReady );
+        }
+
+    if ( !iThreadCreated )
+        {
+        PRINT((_L("CCMRAudioRecorder::PrepareL() no thread")));
+        User::Leave( KErrNotReady );
+        }
+
+    // set priority settings
+    User::LeaveIfError( iThreadProxy.SetPriority(iPrioritySettings));    
+    
+    // give handle to the audio codec
+    User::LeaveIfError( iThreadProxy.SetAudioCodec( iAudioCodecs->GetCodecDataL() ) );
+
+    // inform sink about average audio bitrate
+    User::LeaveIfError( iOutputAO->SetAverageAudioBitRate(iAudioCodecs->GetCodecDataL()->GetBitRateL()) );
+
+    // prime the audio thread
+    User::LeaveIfError(iThreadProxy.Prime());
+    PRINT((_L("CCMRAudioRecorder::PrepareL(), iThreadProxy.Prime() done") ));
+
+    //no need to be in preparing state; prepare is synchronous
+
+    SetState( EStateReadyToRecord );
+    iObserver->MaroStateChange( State() );
+
+    PRINT((_L("CCMRAudioRecorder::PrepareL() out    ")));
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CCMRAudioRecorder::RecordL
+//
+// Start recording
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioRecorder::RecordL()
+    {
+    PRINT((_L("CCMRAudioRecorder::RecordL() in    ")));
+    if ( (State() == EStateRecording) || (State() == EStatePaused) )
+        {
+        // ignore, already recording
+        return;
+        }
+    
+    if ( State() != EStateReadyToRecord )
+        {
+        PRINT((_L("CCMRAudioRecorder::RecordL() wrong state")));
+        User::Leave(KErrNotReady);
+        }
+
+    if ( State() == EStateReadyToRecord )
+        {
+        User::LeaveIfError(iThreadProxy.Play());
+
+        SetState( EStateRecording );
+        iObserver->MaroStateChange( State() );
+        }
+
+    PRINT((_L("CCMRAudioRecorder::RecordL() out    ")));
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioRecorder::StopL
+//
+// Stop recording
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioRecorder::StopL()
+    {
+    PRINT((_L("CCMRAudioRecorder::StopL() in    ")));
+
+    if ( (State() == EStateRecording) || (State() == EStatePaused) )
+        {
+
+        User::LeaveIfError(iThreadProxy.Stop());
+        SetState( EStateStopping );
+        }
+    PRINT((_L("CCMRAudioRecorder::StopL() out    ")));
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioRecorder::PauseL
+//
+// Pause recording
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioRecorder::PauseL()
+    {
+    if ( State() == EStateRecording )
+        {
+        User::LeaveIfError(iThreadProxy.Pause());
+        // pause was sync
+        SetState( EStatePaused );
+        iObserver->MaroStateChange( State() );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioRecorder::ResumeL
+//
+// Resume recording
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioRecorder::ResumeL()
+    {
+    if ( State() == EStatePaused )
+        {
+        User::LeaveIfError(iThreadProxy.Play());
+
+        SetState( EStateRecording );
+        iObserver->MaroStateChange( State() );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioRecorder::WaitUntilStoppedL
+// Wait until audio thread has stopped recording
+// 
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioRecorder::WaitUntilStoppedL()
+    {
+    if ( (State() == EStateRecording) || (State() == EStatePaused) || (State() == EStateStopping))
+        {
+        // not stopped yet
+        User::LeaveIfError(iThreadProxy.WaitUntilStopped());
+        // wait was sync
+        SetState( EStateReadyToRecord );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioRecorder::AVSyncAdjustmentStart
+// Get default AV sync adjustment for start of recording, depending on codec type
+// 
+// -----------------------------------------------------------------------------
+//
+TInt CCMRAudioRecorder::AVSyncAdjustmentStart()
+    {
+    if ( iConfig && iConfig->IsICMConfigDataAvailable() )
+        {
+		return iConfig->VideoQualitySettings().iAVSyncStartDelay;
+        }
+    
+    TCMRCodecType type = ECodecTypeSW;
+
+    TRAPD(err, type = iAudioCodecs->GetCodecDataL()->GetCodecSWHWTypeL());
+    ARASSERT( err == KErrNone );
+    if ( err ) {}
+
+    if ( type == ECodecTypeHW )
+        {
+        //HW codecs (DevSound outputs compressed data)
+        return KCMRInitialVideoAudioTimeSyncHW;
+        }
+    else
+        {
+        //SW codecs (DevSound outputs PCM)
+        return KCMRInitialVideoAudioTimeSyncSW;
+        }
+
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioRecorder::AVSyncAdjustmentResume
+// Get default AV sync adjustment for resume of recording, depending on codec type
+// 
+// -----------------------------------------------------------------------------
+//
+TInt CCMRAudioRecorder::AVSyncAdjustmentResume()
+    {
+    if ( iConfig && iConfig->IsICMConfigDataAvailable() )
+        {
+		return iConfig->VideoQualitySettings().iAVSyncResumeDelay;
+        }
+    
+    TCMRCodecType type = ECodecTypeSW;
+
+    TRAPD(err, type = iAudioCodecs->GetCodecDataL()->GetCodecSWHWTypeL());
+    ARASSERT( err == KErrNone );
+    if ( err ) {}
+
+    if ( type == ECodecTypeHW )
+        {
+        //HW codecs (DevSound outputs compressed data)
+        return KCMRPauseVideoAudioTimeSyncHW;
+        }
+    else
+        {
+        //SW codecs (DevSound outputs PCM)
+        return KCMRPauseVideoAudioTimeSyncSW;
+        }
+
+    }
+
+// -----------------------------------------------------------------------------
+// CCMRAudioRecorder::HandleEvent
+// Handle event from audio thread
+//
+// -----------------------------------------------------------------------------
+//
+void CCMRAudioRecorder::HandleEvent(const TMMFEvent& aEvent)
+    {
+    PRINT((_L("CCMRAudioRecorder::HandleEvent(), aEvent.iEventType %d   aEvent.iErrorCode %d"), aEvent.iEventType.iUid, aEvent.iErrorCode ));
+
+    if (aEvent.iEventType == KMMFEventCategoryPlaybackComplete)
+        {
+        // Lose of audio resource is signalled like this. Also some errors are signaled using this event
+        // If aEvent.iErrorCode == KErrDied, dev policy kicked us out, if it is something else, some other error occurred
+        // audio-thread goes to stopped state before sending this
+        SetState( EStateReadyToRecord );
+        iObserver->MaroStateChange( State() );
+        iObserver->MaroError( aEvent.iErrorCode );
+        PRINT((_L("CCMRAudioRecorder::HandleEvent(), state changed to ready and error informed") ));
+        }
+    else if (aEvent.iErrorCode != KErrNone ) 
+        {
+        if ( aEvent.iErrorCode == KErrServerTerminated )
+            {
+            // audio thread terminated, no need to stop etc anything
+            PRINT((_L("CCMRAudioRecorder::HandleEvent(), audio thread terminated") ));
+            SetState( EStateNone );
+            iObserver->MaroError( aEvent.iErrorCode );
+            iObserver->MaroStateChange( State() );
+            }
+        else
+            {
+            // some other event, e.g. OOM
+            if ( (State() == EStateRecording) || (State() == EStatePaused) )
+                { 
+                // stop first
+                PRINT((_L("CCMRAudioRecorder::HandleEvent(), error received but must stop first") ));
+                iErrorCode = aEvent.iErrorCode;
+                if ( iThreadProxy.Stop() == KErrNone )
+                    {
+                    // wait until stopped
+                    iThreadProxy.WaitUntilStopped();
+                    // wait was sync, can proceed with error handling
+                    }
+                }
+            //inform observer about error
+            SetState( EStateNone );
+            iObserver->MaroError( aEvent.iErrorCode );
+            iObserver->MaroStateChange( State() );
+            PRINT((_L("CCMRAudioRecorder::HandleEvent(), state changed to ready and error informed") ));
+            }
+        }
+    else
+        {
+        // some event without an errorcode! Don't know if this is possible
+        }
+
+    }