--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tactilefeedback/tactilefeedbackresolver/plugins/tactilehapticsplugin/src/tactilehapticsplayer.cpp Thu Dec 17 08:53:38 2009 +0200
@@ -0,0 +1,678 @@
+/*
+* Copyright (c) 2008 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: Class for producing haptics feedback.
+* Part of: Tactile Feedback.
+*
+*/
+
+
+#include <f32file.h>
+#include <e32debug.h>
+#include <hwrmhaptics.h>
+#include <centralrepository.h>
+#include <ecom/implementationproxy.h>
+#include <MProfileEngine.h>
+#include <MProfile.h>
+#include <MProfileExtraSettings.h>
+#include <MProfileFeedbackSettings.h>
+#include <CProfileChangeNotifyHandler.h>
+
+#include "tactilefeedbackprivatecrkeys.h"
+#include "tactilefeedbacktrace.h"
+
+#include "tactilehapticsplayer.h"
+#include "OstTraceDefinitions.h"
+#ifdef OST_TRACE_COMPILER_IN_USE
+#include "tactilehapticsplayerTraces.h"
+#endif
+
+// ======== MEMBER FUNCTIONS ========
+
+const TInt KMaxEffectNameLen = 128;
+
+// Pulse feedback's names
+_LIT8( KTFBasic, "TFBasic");
+_LIT8( KTFSensitive, "TFSensitive");
+_LIT8( KTFBasicButton, "TFBasicButton");
+_LIT8( KTFSensitiveButton, "TFSensitiveButton");
+_LIT8( KTFList, "TFList");
+_LIT8( KTFSensitiveList, "TFSensitiveList");
+_LIT8( KTFBoundaryList, "TFBoundaryList");
+_LIT8( KTFSlider, "TFSlider");
+_LIT8( KTFEdit, "TFEdit");
+_LIT8( KTFLineSelection, "TFLineSelection");
+_LIT8( KTFBlankSelection, "TFBlankSelection");
+_LIT8( KTFTextSelection, "TFTextSelection");
+_LIT8( KTFEmptyLineSelection, "TFEmptyLineSelection");
+_LIT8( KTFTab, "TFTab");
+_LIT8( KTFPopUp, "TFPopUp");
+_LIT8( KTFIncreasingPopUp, "TFIncreasingPopUp");
+_LIT8( KTFDecreasingPopUp, "TFDecreasingPopUp");
+_LIT8( KTFFlick, "TFFlick");
+_LIT8( KTFCheckbox, "TFCheckbox");
+_LIT8( KTFSensitiveInput, "TFSensitiveInput");
+_LIT8( KTFCharacterInputButton, "TFCharacterInputButton");
+_LIT8( KTFMultiTouchRecognized, "TFMultiTouchRecognized");
+
+// Continuous feedback's names
+_LIT8( KTFContinuousSmooth, "TFContinuousSmooth");
+_LIT8( KTFContinuousSlider, "TFContinuousSlider");
+_LIT8( KTFContinuousInput, "TFContinuousInput");
+_LIT8( KTFContinuousFlick, "TFContinuousFlick");
+// ---------------------------------------------------------------------------
+// Constructor.
+// ---------------------------------------------------------------------------
+//
+CTactileHapticsPlayer::CTactileHapticsPlayer( CRepository& aRepository ) :
+ iRepository(aRepository)
+ {
+
+ }
+
+// ---------------------------------------------------------------------------
+// 2nd phase constructor.
+// ---------------------------------------------------------------------------
+//
+void CTactileHapticsPlayer::ConstructL()
+ {
+ TRACE("CTactileHapticsPlayer::ConstructL - Begin");
+ iHaptics = CHWRMHaptics::NewL(NULL, NULL);
+
+ TUint32 suppMask( 0 );
+ User::LeaveIfError( iHaptics->SupportedActuators( suppMask ) );
+
+ TInt actuatorType( EHWRMLogicalActuatorAny );
+ iRepository.Get( KTactileFeedbackHapticsActuator, actuatorType );
+
+ if ( actuatorType & suppMask )
+ {
+ iHaptics->OpenActuatorL( static_cast<THWRMLogicalActuators>(actuatorType) );
+ }
+
+ User::LeaveIfError( iHaptics->SetDeviceProperty(
+ CHWRMHaptics::EHWRMHapticsLicensekey,
+ KNullDesC8() ) );
+
+ TInt strength(0);
+ iRepository.Get( KTactileFeedbackHapticsStrength, strength );
+
+ // Strength value in settings is multiplied by 100 to scale value
+ // suitable for haptics (0-10000).
+ iStrength = strength * 100;
+
+ // As a temporary fix to EAKH-7LKANT, the strength is (over)read from
+ // profiles engine
+ InitializeProfilesEngineL();
+
+ User::LeaveIfError( iHaptics->SetDeviceProperty(
+ CHWRMHaptics::EHWRMHapticsStrength,
+ iStrength ) );
+ TFileName ivtFile;
+ iRepository.Get( KTactileHapticsIVTFile, ivtFile );
+ HBufC8* ivtBuf = IVTBufAllocL( ivtFile );
+
+ CleanupStack::PushL( ivtBuf );
+ User::LeaveIfError( iHaptics->LoadEffectData( *ivtBuf, iIVTHandle ) );
+ CleanupStack::PopAndDestroy( ivtBuf );
+
+ iCenRepNotifier = CCenRepNotifyHandler::NewL( *this,
+ iRepository );
+ iCenRepNotifier->StartListeningL();
+
+ TRACE("CTactileHapticsPlayer::ConstructL - End");
+ }
+
+// ---------------------------------------------------------------------------
+// 2-phased constructor.
+// ---------------------------------------------------------------------------
+//
+CTactileHapticsPlayer* CTactileHapticsPlayer::NewL( CRepository& aRepository )
+ {
+ CTactileHapticsPlayer* self =
+ new ( ELeave ) CTactileHapticsPlayer( aRepository );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// Destructor.
+// ---------------------------------------------------------------------------
+//
+CTactileHapticsPlayer::~CTactileHapticsPlayer()
+ {
+ if( iProfileEng )
+ {
+ iProfileEng->Release();
+ iProfileEng = NULL;
+ }
+ delete iProfileHandler;
+ delete iCenRepNotifier;
+ delete iHaptics;
+ }
+
+// ---------------------------------------------------------------------------
+// From class CTactilePlayer
+//
+// ---------------------------------------------------------------------------
+//
+TInt CTactileHapticsPlayer::PlayFeedback( TTouchLogicalFeedback aFeedback )
+ {
+ // TRACE("CTactileHapticsPlayer::PlayFeedback - Start");
+
+ TRACE2("CTactileHapticsPlayer::PlayFeedback type: %d", aFeedback );
+ TRAPD( err, DoPlayFeedbackL( aFeedback ));
+ if ( err != KErrNone )
+ {
+ TRACE2("CTactileHapticsPlayer::PlayFeedback error: %d", err );
+ }
+
+ // TRACE("CTactileHapticsPlayer::PlayFeedback - End");
+ return err;
+ }
+
+// ---------------------------------------------------------------------------
+// Actually play feedback.
+// ---------------------------------------------------------------------------
+//
+void CTactileHapticsPlayer::DoPlayFeedbackL( TTouchLogicalFeedback aFeedback )
+ {
+ // Check if hapticts strength is set to zero.
+ if ( !iStrength )
+ {
+ User::Leave(KErrNotReady);
+ }
+
+ TBuf8<KMaxEffectNameLen> name;
+
+ switch( aFeedback )
+ {
+ case ETouchFeedbackBasic:
+ name = KTFBasic;
+ break;
+ case ETouchFeedbackSensitive:
+ name = KTFSensitive;
+ break;
+ case ETouchFeedbackBasicButton:
+ name = KTFBasicButton;
+ break;
+ case ETouchFeedbackSensitiveButton:
+ name = KTFSensitiveButton;
+ break;
+ case ETouchFeedbackList:
+ name = KTFList;
+ break;
+ case ETouchFeedbackSensitiveList:
+ name = KTFSensitiveList;
+ break;
+ case ETouchFeedbackBoundaryList:
+ name = KTFBoundaryList;
+ break;
+ case ETouchFeedbackSlider:
+ name = KTFSlider;
+ break;
+ case ETouchFeedbackEdit:
+ name = KTFEdit;
+ break;
+ case ETouchFeedbackLineSelection:
+ name = KTFLineSelection;
+ break;
+ case ETouchFeedbackBlankSelection:
+ name = KTFBlankSelection;
+ break;
+ case ETouchFeedbackTextSelection:
+ name = KTFTextSelection;
+ break;
+ case ETouchFeedbackEmptyLineSelection:
+ name = KTFEmptyLineSelection;
+ break;
+ case ETouchFeedbackTab:
+ name = KTFTab;
+ break;
+ case ETouchFeedbackPopUp:
+ name = KTFPopUp;
+ break;
+ case ETouchFeedbackIncreasingPopUp:
+ name = KTFIncreasingPopUp;
+ break;
+ case ETouchFeedbackDecreasingPopUp:
+ name = KTFDecreasingPopUp;
+ break;
+ case ETouchFeedbackFlick:
+ name = KTFFlick;
+ break;
+ case ETouchFeedbackCheckbox:
+ name = KTFCheckbox;
+ break;
+ case ETouchFeedbackSensitiveInput:
+ name = KTFSensitiveInput;
+ break;
+ case ETouchFeedbackCharacterInputButton:
+ name = KTFCharacterInputButton;
+ break;
+ case ETouchFeedbackMultiTouchRecognized:
+ name = KTFMultiTouchRecognized;
+ break;
+ default:
+ User::Leave( KErrArgument );
+ break;
+ }
+ TInt effectIndex(0);
+ User::LeaveIfError( iHaptics->GetEffectIndexFromName( iIVTHandle,
+ name,
+ effectIndex ) );
+ TInt effectHandle(0);
+ OstTrace0( TACTILE_PERFORMANCE, TACTILE_PLAY_HAPTICS_FEEDBACK_1, "e_TACTILE_PLAY_HAPTICS_FEEDBACK 1");
+ User::LeaveIfError( iHaptics->PlayEffect( iIVTHandle,
+ effectIndex,
+ effectHandle ) );
+ OstTrace0( TACTILE_PERFORMANCE, TACTILE_PLAY_HAPTICS_FEEDBACK_0, "e_TACTILE_PLAY_HAPTICS_FEEDBACK 0");
+ }
+
+// ---------------------------------------------------------------------------
+// Load IVT file.
+// ---------------------------------------------------------------------------
+//
+HBufC8* CTactileHapticsPlayer::IVTBufAllocL( const TDesC& aFileName )
+ {
+ TRACE("CTactileHapticsPlayer::IVTBufAllocL - Begin");
+
+ RFs fs;
+ User::LeaveIfError( fs.Connect() );
+ CleanupClosePushL( fs );
+
+ RFile file;
+ User::LeaveIfError( file.Open( fs, aFileName, EFileRead ) );
+ CleanupClosePushL( file );
+
+ TInt fileSize( 0 );
+ file.Size( fileSize );
+
+ HBufC8* ivtFileBuf = HBufC8::NewLC( fileSize );
+ TPtr8 dataBufPtr = ivtFileBuf->Des();
+
+ User::LeaveIfError( file.Read( dataBufPtr ) );
+
+ CleanupStack::Pop( ivtFileBuf );
+ CleanupStack::PopAndDestroy( &file );
+ CleanupStack::PopAndDestroy( &fs );
+ TRACE("CTactileHapticsPlayer::IVTBufAllocL - End");
+ return ivtFileBuf;
+ }
+
+// ---------------------------------------------------------------------------
+// Start feedback.
+// ---------------------------------------------------------------------------
+//
+TInt CTactileHapticsPlayer::StartFeedback( TTouchContinuousFeedback aFeedback,
+ TInt aIntensity )
+ {
+ TRACE("CTactileHapticsPlayer::StartFeedback - Start");
+ TInt ret(KErrNone);
+
+ // If there's an ongoing feedback, stop it first.
+ if ( iEffectHandle )
+ {
+ StopFeedback();
+ }
+
+ TBuf8<KMaxEffectNameLen> name;
+ switch( aFeedback )
+ {
+ case ETouchContinuousSmooth:
+ name = KTFContinuousSmooth;
+ break;
+ case ETouchContinuousSlider:
+ name = KTFContinuousSlider;
+ break;
+ case ETouchContinuousInput:
+ name = KTFContinuousInput;
+ break;
+ case ETouchContinuousFlick:
+ name = KTFContinuousFlick;
+ break;
+ default:
+ ret = KErrArgument;
+ break;
+ }
+
+ if ( ret == KErrNone )
+ {
+ ret = iHaptics->GetEffectIndexFromName( iIVTHandle,
+ name,
+ iEffectIndex );
+ }
+
+ TInt effectType(0);
+ if ( ret == KErrNone )
+ {
+ ret = iHaptics->GetEffectType( iIVTHandle,
+ iEffectIndex,
+ effectType );
+ }
+
+ if ( ret == KErrNone )
+ {
+ switch ( effectType )
+ {
+ case CHWRMHaptics::EHWRMHapticsTypePeriodic:
+ {
+ CHWRMHaptics::THWRMHapticsPeriodicEffect periodicDef;
+
+ ret = iHaptics->GetPeriodicEffectDefinition( iIVTHandle,
+ iEffectIndex,
+ periodicDef );
+
+ // Effect's magnitude value in IVT file is used as max value for
+ // continuous effects.
+ iMultiplier = periodicDef.iMagnitude / 100;
+ periodicDef.iMagnitude = aIntensity * iMultiplier;
+
+ if ( ret == KErrNone )
+ {
+ ret = iHaptics->PlayPeriodicEffect( periodicDef,
+ iEffectHandle );
+ }
+ }
+ break;
+ case CHWRMHaptics::EHWRMHapticsTypeMagSweep:
+ {
+ CHWRMHaptics::THWRMHapticsMagSweepEffect magSweepDef;
+
+ ret =iHaptics->GetMagSweepEffectDefinition( iIVTHandle,
+ iEffectIndex,
+ magSweepDef );
+
+ // Effect's magnitude value in IVT file is used as max value for
+ // continuous effects.
+ iMultiplier = magSweepDef.iMagnitude / 100;
+ magSweepDef.iMagnitude = aIntensity * iMultiplier;
+
+ if ( ret == KErrNone )
+ {
+ ret =iHaptics->PlayMagSweepEffect( magSweepDef,
+ iEffectHandle );
+ }
+ }
+ break;
+ default:
+ TRACE("CTactileHapticsPlayer::StartFeedback - Playing effect not found");
+ ret = KErrArgument;
+ break;
+ }
+ }
+
+ TRACE("CTactileHapticsPlayer::StartFeedback - End");
+ return ret;
+ }
+
+// ---------------------------------------------------------------------------
+// Modify feedback.
+// ---------------------------------------------------------------------------
+//
+TInt CTactileHapticsPlayer::ModifyFeedback( TInt aIntensity )
+ {
+ TRACE("CTactileHapticsPlayer::ModifyFeedback - Start");
+ TInt ret(KErrNotReady);
+
+ // Check if there's feedback started, do nothing if not.
+ if ( iEffectHandle )
+ {
+ TInt effectType(0);
+
+ ret = iHaptics->GetEffectType( iIVTHandle,
+ iEffectIndex,
+ effectType );
+
+ TRACE2("CTactileHapticsPlayer::ModifyFeedback - effect type %d", effectType );
+
+ if ( ret == KErrNone )
+ {
+ TInt intensity = aIntensity * iMultiplier;
+
+ switch ( effectType )
+ {
+ case CHWRMHaptics::EHWRMHapticsTypePeriodic:
+ {
+ CHWRMHaptics::THWRMHapticsPeriodicEffect periodicDef;
+
+ iHaptics->GetPeriodicEffectDefinition( iIVTHandle,
+ iEffectIndex,
+ periodicDef );
+
+ periodicDef.iMagnitude = intensity;
+
+ iHaptics->ModifyPlayingPeriodicEffect( iEffectHandle,
+ periodicDef );
+ }
+ break;
+ case CHWRMHaptics::EHWRMHapticsTypeMagSweep:
+ {
+ CHWRMHaptics::THWRMHapticsMagSweepEffect magSweepDef;
+
+ iHaptics->GetMagSweepEffectDefinition( iIVTHandle,
+ iEffectIndex,
+ magSweepDef );
+
+ magSweepDef.iMagnitude = intensity;
+
+ iHaptics->ModifyPlayingMagSweepEffect( iEffectHandle,
+ magSweepDef );
+
+ }
+ break;
+ default:
+ ret = KErrArgument;
+ break;
+ }
+ }
+ }
+
+ TRACE("CTactileHapticsPlayer::ModifyFeedback - End");
+ return ret;
+ }
+
+// ---------------------------------------------------------------------------
+// Stop feedback.
+// ---------------------------------------------------------------------------
+//
+void CTactileHapticsPlayer::StopFeedback()
+ {
+ TRACE("CTactileHapticsPlayer::StopFeedback - Start");
+ iHaptics->StopAllPlayingEffects();
+ iEffectHandle = 0;
+ TRACE("CTactileHapticsPlayer::StopFeedback - End");
+ }
+
+// ---------------------------------------------------------------------------
+// Check if there's a change in haptics settings and set new values if needed.
+// ---------------------------------------------------------------------------
+//
+void CTactileHapticsPlayer::DoHandleNotifyGenericL( TUint32 aId )
+ {
+ TRACE("CTactileHapticsPlayer::DoHandleNotifyGenericL - Begin");
+ switch ( aId )
+ {
+ case KTactileFeedbackHapticsStrength:
+ {
+ // Strength value in settings is multiplied by 100 to scale value
+ // suitable for haptics.
+ TInt strength(0);
+ iRepository.Get( KTactileFeedbackHapticsStrength, strength );
+
+ iStrength = strength * 100;
+ iHaptics->SetDeviceProperty( CHWRMHaptics::EHWRMHapticsStrength,
+ iStrength );
+ }
+ break;
+ case KTactileHapticsIVTFile:
+ {
+ TFileName ivtFile;
+ iRepository.Get( KTactileHapticsIVTFile, ivtFile );
+
+ HBufC8* ivtBuf = IVTBufAllocL( ivtFile );
+ if ( ivtBuf )
+ {
+ TInt ret = iHaptics->DeleteEffectData( iIVTHandle );
+ if ( ret == KErrNone )
+ {
+ iHaptics->LoadEffectData( *ivtBuf, iIVTHandle );
+ }
+ delete ivtBuf;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ TRACE("CTactileHapticsPlayer::DoHandleNotifyGenericL - End");
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+TInt CTactileHapticsPlayer::PlayPreviewFeedback( TInt aLevel,
+ TTouchLogicalFeedback aFeedback )
+ {
+ TRACE("CTactileHapticsPlayer::PlayPreviewFeedback - Begin");
+ // Set preview level (scaled to haptics - multiplied by 100).
+ TInt ret = iHaptics->SetDeviceProperty( CHWRMHaptics::EHWRMHapticsStrength,
+ aLevel * 100 );
+ if ( ret == KErrNone )
+ {
+ ret = PlayFeedback( aFeedback );
+ }
+
+ iHaptics->SetDeviceProperty( CHWRMHaptics::EHWRMHapticsStrength,
+ iStrength );
+
+ TRACE("CTactileHapticsPlayer::PlayPreviewFeedback - End");
+ return ret;
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+TInt CTactileHapticsPlayer::StartPreviewFeedback( TInt aLevel,
+ TTouchContinuousFeedback aFeedback,
+ TInt aIntensity )
+ {
+ TRACE("CTactileHapticsPlayer::StartPreviewFeedback - Begin");
+ // Set preview level (scaled to haptics - multiplied by 100).
+ TInt ret = iHaptics->SetDeviceProperty( CHWRMHaptics::EHWRMHapticsStrength,
+ aLevel * 100 );
+ if ( ret == KErrNone )
+ {
+ ret = StartFeedback( aFeedback, aIntensity );
+ }
+ TRACE("CTactileHapticsPlayer::StartPreviewFeedback - End");
+ return ret;
+ }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void CTactileHapticsPlayer::StopPreviewFeedback()
+ {
+ TRACE("CTactileHapticsPlayer::StopPreviewFeedback - Begin");
+ StopFeedback();
+
+ iHaptics->SetDeviceProperty( CHWRMHaptics::EHWRMHapticsStrength,
+ iStrength );
+ TRACE("CTactileHapticsPlayer::StopPreviewFeedback - Begin");
+ }
+
+// ---------------------------------------------------------------------------
+// From MCenRepNotifyHandlerCallback.
+// ---------------------------------------------------------------------------
+//
+void CTactileHapticsPlayer::HandleNotifyGeneric( TUint32 aId )
+ {
+ TRACE("CTactileHapticsPlayer::HandleNotifyGeneric - Begin");
+ TRAP_IGNORE( DoHandleNotifyGenericL( aId ) );
+ TRACE("CTactileHapticsPlayer::HandleNotifyGeneric - End");
+ }
+
+// ---------------------------------------------------------------------------
+// From MProfileChangeObserver.
+// ---------------------------------------------------------------------------
+//
+void CTactileHapticsPlayer::HandleActiveProfileEventL(
+ TProfileEvent /*aProfileEvent*/,
+ TInt /*aProfileId*/ )
+ {
+ InitializeProfilesEngineL();
+ iHaptics->SetDeviceProperty( CHWRMHaptics::EHWRMHapticsStrength, iStrength );
+ }
+
+// ---------------------------------------------------------------------------
+// Profiles engine -related initializations
+// ---------------------------------------------------------------------------
+//
+void CTactileHapticsPlayer::InitializeProfilesEngineL()
+ {
+ // Create profiles engine, if it does not yet exist
+ if ( !iProfileEng )
+ {
+ iProfileEng = CreateProfileEngineL();
+ }
+
+ MProfile* activeProfile = iProfileEng->ActiveProfileL();
+
+ const MProfileExtraSettings& extraSettings =
+ activeProfile->ProfileExtraSettings();
+
+ const MProfileFeedbackSettings& feedbackSettings =
+ extraSettings.ProfileFeedbackSettings();
+
+ TProfileTactileFeedback strength = feedbackSettings.TactileFeedback();
+ iStrength = 100 * ( EProfileTactileFeedbackLevel3 == strength ? 100 :
+ EProfileTactileFeedbackLevel2 == strength ? 60 :
+ EProfileTactileFeedbackLevel1 == strength ? 30 : 0 );
+
+ activeProfile->Release();
+
+ // Create listener for profiles changes, if it does not yet exist
+ if ( !iProfileHandler )
+ {
+ iProfileHandler = CProfileChangeNotifyHandler::NewL( this );
+ }
+ }
+
+//---------------------------------------------------------------------------
+// ImplementationTable[]
+//
+//---------------------------------------------------------------------------
+//
+const TImplementationProxy ImplementationTable[] =
+ {
+ IMPLEMENTATION_PROXY_ENTRY( 0x2001CB99, CTactileHapticsPlayer::NewL )
+ };
+
+//---------------------------------------------------------------------------
+// TImplementationProxy* ImplementationGroupProxy()
+//
+//---------------------------------------------------------------------------
+//
+EXPORT_C const TImplementationProxy* ImplementationGroupProxy( TInt& aTableCount )
+ {
+ aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy);
+ return ImplementationTable;
+ }
+
+// End of file