Purpose

With the Haptics API it is possible to produce haptic effects and control their behavior in the device. E.g., playing an explosion effect in a game with the device's vibration feature allows the user to feel the haptic feedback in his hand. The purpose of this API is to provide developers an easy way to create and use haptic effects. This API provides application developers a unified interface across different products. The actual physical vibration and/or motion depends on the settings and the device's configuration. This document is valid from release 5.1 onwards.

There are also a few related APIs:

  • Tactile Feedback API is used to produce simple haptic feedback, e.g., from UI controls.

  • Tacticons API is used to play tacticons.

Both of these APIs use the Haptics API to play the actual effects. Often, in order to produce just simple haptic effects, it is recommended to use these two APIs instead of the Haptics API directly.

In addition, the Vibra API is available for even simpler vibration effects.

Constraints

  • This API is valid for all devices running on Symbian OS, S60 5.1 or later releases.

  • Periodic effects accurately produce vibration frequencies up to ca. 30 Hz, depending on the device.

  • Depending on the device, only a subset of all possible logical actuators can be supported.

Classification and release information

This API is an SDK API and was first published for Symbian OS, S60 5.1.

Emulator support

The Haptics API has limited support in the WINS/WINSCW emulator environment. Obviously, it is not possible to feel the physical vibrations in emulator environment. In target environment, the adaptation layer plug-in dispatches various haptics-related requests and responses between the API and physical vibration device driver service. In emulator environment, the plug-in is just a stub that emulates successful functionality.

API description

The Haptics API provides methods for controlling the haptics feature of the device. Both synchronous and asynchronous versions are provided for playing various types of effects. Only synchronous methods are provided for other functionalities, such as opening and closing an actuator, reserving and releasing the haptics feature, and for getting various state and system information from the haptics. This API is meant for any application that needs to control the device's haptics feature.

The Haptics API is a Library API that has been implemented using the client-server architecture. Most of the processing is done on the server side, the client side acting mostly as a message passing proxy. However, there is a cache of loaded effect data that is handled in the client side.

The Haptics API does not require any platform security capabilities.

Use cases

The most common use cases are listed below:

Initialization

  • Enquiring which logical actuators are supported by the device

  • Opening a supported logical actuator

  • Enquiring the capabilities of an actuator

  • Setting the license key

Playing the effects

  • Playing magnitude sweep effects

  • Playing periodic effects

  • Playing all kinds of effects (including timeline effects) that are defined in an effect data buffer read, for example, from a file

  • Repeating effects (applicable for timeline effects)

  • Creating and playing streaming effects

  • Playing multiple effects at the same time

  • Pausing and resuming the playing of effects

  • Stopping a specific effect or all effects that are playing

  • Enquiring the state of the effects (whether playing, paused or not playing)

Using two or more haptics instances

  • Automatic priority handling via setting the priority level of the client when using the same logical actuator

  • Playing multiple effects via different haptics instances

  • Reserving, and later releasing, the haptics feature for exclusive use

Effects defined in effect data buffers

  • Loading one or more effect data buffers for simultaneous use

  • Enquiring information about effects that have been defined within the loaded effect data buffer(s)

  • Deleting/unloading effect data buffers after use

API class structure

The client creates an instance of the Haptics API's main class CHWRMHaptics . If a callback interface is required, the client must implement the appropriate M class and provide a pointer to the corresponding implementation object when instantiating the CHWRMHaptics object. The THWRMLogicalActuators enumeration lists the available logical actuators. Some of the logical actuators listed in the enumeration may not be supported in a particular device. Therefore, before trying to open an actuator, the developer must check which logical actuators are actually supported in the device.

API class structure


API class structure

Related APIs
  • CHWRMHaptics
  • THWRMLogicalActuators

Using the Haptics API

In general, using the API consists of the following steps:

  • Link the Haptics library ( hwrmhapticsclient.lib ) to the client application.

  • Instantiate an instance of the CHWRMHaptics class using the NewL() static method.

    Give pointers to objects that implement the MHWRMHapticsObserver and MHWRMHapticsActuatorObserver abstract interfaces to NewL() if you want to use observers for haptics-related notifications.

  • Get a bitmask of supported logical actuators by calling SupportedActuators() .

  • Open a supported logical actuator by calling OpenActuatorL() .

  • Set the license key by calling SetDeviceProperty() with the EHWRMHapticsLicensekey property.

  • After the above steps, the rest of the haptics functionality is ready to be used. This includes playing various types of effects, loading effect definitions (from effect data buffers), enquiring actuator capabilities, modifying the effects, etc.

  • More detailed instructions for using the API are given in the following sections.

    Preparing Haptics API for use

    The Haptics API must be initialized by following these steps.

    • Instantiate.

    • Get supported logical actuators.

    • Open a supported logical actuator that is most suitable for the application.

    • Set the license key.

    If these steps are not followed, the API is unusable as most methods fail and return either KErrNotReady or KErrAccessDenied error code.

    To use all methods of the API, the client must open a logical actuator that is supported in the system and must set a valid license key.

    Instantiating with and without observers

    First the developer must create an instance of the haptics by calling the static NewL() method. The NewL() method takes pointers to MHWRMHapticsObserver and MHWRMHapticsActuatorObserver as arguments. These can be set to NULL if the developer does not want to observe haptics-related status change notifications.

                  
                   // CMyClass example myclass.h file
                   

    #include <hwrmhaptics.h>


    class CMyClass : public MHWRMHapticsObserver, MHWRMHapticsActuatorObserver
        {
        public:

            static CMyClass NewL();
            ~CMyClass();

        public:

            /**
             * Inherited from MHWRMHapticsObserver
             */

            /**
             * Notification of status changes of the haptics feature itself
             * such as e.g. EHWRMHapticsStatusOn or EHWRMHapticsStatusStopped
             */
            void HapticsStatusChangedL( THWRMHapticsStatus aStatus );

        /**
             * Notification of the completion of playing of an effect
             */
            void EffectCompletedL( TInt aError, TInt aEffectHandle );

       public: 

            /**
             * Inherited from MHWRMHapticsActuatorObserver
             */

            /**
             * Notification of logical actuator related event. Currently
             * there are events defined for attaching an actuator, 
             * detaching an actuator, and for enabling and disabling one
             */
            void ActuatorEventL( THWRMActuatorEvents aEvent, THWRMLogicalActuators aActuator );

        private:
          
            CMyClass();
            void ConstructL();
            void InitializeActuatorL( const TDesC8& aLicenseKey );

        private:

            CHWRMHaptics* iHaptics;
        };

    // ...

    // ------------------------------------------

    // CMyClass example *.cpp file

    #include "myclass.h"

    void CMyClass::ConstructL()
        {
        // Instantiating with no observers
        iHaptics = CHWRMHaptics::NewL( NULL, NULL );
        
        // Example for instantiating with haptics status observer
        CHWRMHaptics* haptics1 = CHWRMHaptics::NewL( this, NULL );
        CleanupStack::PushL( haptics1 );

        // Example for instantiating with both haptics status observer and actuator observer
        CHWRMHaptics* haptics2 = CHWRMHaptics::NewL( this, this );
        CleanupStack::PushL( haptics2 );

        // ... 

        CleanupStack::PopAndDestroy( haptics2 );
        CleanupStack::PopAndDestroy( haptics1 );
        }
    Related APIs
    • MHWRMHapticsActuatorObserver
    • MHWRMHapticsObserver
    • NULL
    • NewL()

    Checking supported logical actuators

    Checking which logical actuators are supported in the device is done by calling the SupportedActuators() method. As a parameter, the method takes a reference to a TUint32 variable, which contains a bitmask of supported logical actuators. The bitmask is populated using THWRMLogicalActuators enumerations, and can be evaluated using bitwise operators with these enumerations. An example is shown below.

                  
                   ...
                   

    // Variable for receiving the bitmask of logical actuators supported in the device.
    TUint32 suppActuators( 0 );

    User::LeaveIfError( iHaptics->SupportedActuators( suppActuators ) );

    // Check the returned bitmask against logical actuators enumerations
    // and choose the most suitable for the given application, e.g.
    if ( EHWRMLogicalActuatorGame & suppActuators )
        {
        // Open the most suitable supported actuator (see next section)
        }
    else if ( EHWRMLogicalActuatorDevice & suppActuators )
        {
        // Open the second most suitable supported actuator 
        }
    // etc.
    Related APIs
    • SupportedActuators()
    • THWRMLogicalActuators
    • TUint32

    Opening a supported logical actuator

    Opening the actuator is done by calling the OpenActuatorL() method. Immediately after opening an actuator, it is necessary to set a license key for the haptics in order to unlock the Haptics API's full functionality. The license key is set by calling the SetDeviceProperty() method for the EHWRMHapticsLicensekey property. The property value must be set to a platform-dependent license key issued by Nokia Developer.

                  
                   // Note: License keys are 32 bytes long data buffers of TUint8 data
                   
    void CMyClass::InitializeActuatorL( const TDesC8& aLicenseKey )
        {
        // open a supported logical actuator
        iHaptics->OpenActuatorL( EHWRMLogicalActuatorGame );

        // set the license key for the opened logical actuator
        TInt licenseErr( 0 );
        licenseErr = iHaptics->SetDeviceProperty( CHWRMHaptics::EHWRMHapticsLicensekey, aLicenseKey );

        if( licenseErr == KErrAccessDenied )
            {
            // the license key was wrong
            }
        }
    Related APIs
    • EHWRMHapticsLicensekey
    • OpenActuatorL()
    • SetDeviceProperty()

    Checking the capabilities of a supported logical actuator

    In some cases the application may need to enquire the capabilities of an actuator. For example, it needs to take specific actions depending on, e.g., such capabilities as the number of effect slots or the minimum period for periodic effects.

    The capabilities of a supported logical actuator are checked by calling the GetDeviceCapability() method with one of the THWRMHapticsDeviceCapabilityTypes enumerations as the first parameter. A reference to a variable into which the returned capability value is to be stored is given as the second parameter. Depending on the capability in question, the returned capability value can be an integer or a descriptor containing an 8-bit data buffer. The GetDeviceCapability() method has overloaded versions where the second parameter is either a TInt& reference or a TDes8& reference.

                  
                   // Example: fetching the actuator's minimum period value and name
                   
    TInt minPeriod( 0 ); // variable to receive the mimimun period for periodic effects
    User::LeaveIfError( iHaptics->GetDeviceCapability( CHWRMHaptics::EHWRMHapticsMinPeriod, minPeriod ) );
        
    RBuf8 name;
    name.CreateL( iHaptics->MaxDeviceNameLength() );
    CleanupClosePushL( name );
    User::LeaveIfError( iHaptics->GetDeviceCapability( CHWRMHaptics::EHWRMHapticsDeviceName, name ) );

    // ... 

    CleanupStack::PopAndDestroy( &name );
    Related APIs
    • GetDeviceCapability()
    • TDes8&
    • THWRMHapticsDeviceCapabilityTypes
    • TInt&

    Checking and setting the haptics properties

    The Haptics API provides means for getting and setting some of the haptics properties. The available properties are defined in the THWRMHapticsDevicePropertyType enumeration. These include such items as the already demonstrated license key, various strength and priority settings, and a setting that determines whether the effect playing is disabled or not. Successfully setting some of these can require a prior setting of the OEM license key. The example below shows how to get and set the strength property.

                  
                   // the actuator has been opened and the license key has been set successfully.
                   

    TInt strength;
    User::LeaveIfError( iHaptics->GetDeviceProperty( CHWRMHaptics::EHWRMHapticsStrength, strength ) );

    // E.g., forcing the value to meet the threshold criteria.
    // This setting has an impact on all effects of this client
    if ( strength < 5000 )
       {
       User::LeaveIfError( iHaptics->SetDeviceProperty( CHWRMHaptics::EHWRMHapticsStrength, 5000 ) );
       }
    Related APIs
    • THWRMHapticsDevicePropertyType

    Reserving haptics

    The Haptics API allows a client to exclusively reserve the haptics feature. This may be feasible, e.g., in game applications where the haptic effects from other sources than the game itself may be undesirable. It is possible for a higher priority client application to override previous reservation made by a lower priority application. This new reservation suspends the current reservation until the higher priority reservation is released.

    Note: The suspension applies only to the use of the haptics feature, i.e., except for the haptics, the suspended application can continue its processing normally.

    There are two kinds of reservations: one in which the foreground/background status of the application determines whether the reservation is applied, and one in which the reservation is forced and held by the reserving application regardless of its foreground/background status. Only trusted applications may reserve the haptics in the forced mode. The client application is considered trusted if it has a priority defined in the haptics policy file. The policy files can be modified by the Symbian device manufacturers.

                  
                   // Reserving the haptics
                   
    TBool forcedReserve( EFalse );
    TRAPD( err, iHaptics->ReserveHapticsL( forcedReserve ) );
    if ( !err )
       {
       // haptics is now reserved for this application..
       // ...

       // Release the reservation
       iHaptics->ReleaseHaptics(); // always succeeds 
       }
    Related APIs
    • KErrAccessDenied
    • KErrNotReady

    Effects

    The Haptics API can be used to play different types of effects. There are three categories of effects:

    • Simple (basic) effects

      Simple effects are effects that the developer can create and play at run-time directly using the appropriate API methods as described in Simple effects .

  • Streaming effects

    Streaming effects allow for fine-tuned haptics synchronization, for example, with sound. The application provides periodically smallish effect samples that are then played by the haptics player.

  • Timeline effects

    The timeline effects are constructed from possibly several simple effects that have been scheduled over time. The timeline effects cannot be created and played directly using the API methods. They must be defined in an effect data buffer.

  • Once the effects have been created, the effect-definitions are exported to a binary format file that is loaded to the mobile device. The Haptics API has methods for loading the effect data buffer (read from a file) to the Haptics subsystem and methods for, e.g., playing and modifying the effects contained within the file.

    Note: Although the sections below introduce synchronous versions of the play and modify methods, there are also asynchronous variants of these methods that take a TRequestStatus reference as an argument and return immediately. The synchronous versions of the methods shown in the sections below usually return after the Haptics command data corresponding to the API call has been propagated to Haptics server side and the server has sent back a response. This does not mean that, e.g., the synchronous play method call only returns when the effect has stopped playing. Instead, this means that the server side has received the data needed for playing the effect, evaluated the data, created an effect handle and returned the handle to the client side.

    Simple effects

    There are two types of simple effects: magnitude sweep effects and period effects. Magnitude sweep effects vibrate at a magnitude and device-dependent constant rate (vibration frequency). Periodic effects allow the period of vibration (frequency) to be explicitly controlled independently of magnitude.

    Both magnitude sweep and periodic effects have a set of envelope parameters that control the duration and strength of the vibration. They are defined in THWRMHapticsMagSweepEffect and THWRMHapticsPeriodicEffect structs. Effects can be formed at run-time by creating and filling in structs with effect-specific data, and then played by calling the PlayMagSweepEffect() and PlayPeriodicEffect() methods with the created structs as arguments. There are different effect styles (defined in THWRMHapticsEffectStyles enumeration) that have an impact on the feel of the effects.

    The example below shows how magnitude sweep and periodic effects are formed and played. It also shows a couple of ways to stop playing effects before their defined playing duration expires.

                  
                   /**
                   
    * Defining magnitude sweep effect parameters
    */

    CHWRMHaptics::THWRMHapticsMagSweepEffect magSweepEff;
     
    magSweepEff.iDuration = 5000;                // Duration of the effect in milliseconds.
    magSweepEff.iMagnitude = KHWRMHapticsMaxMagnitude/2;       // Magnitude, 50% of maximum
    magSweepEff.iStyle = CHWRMHaptics::EHWRMHapticsStyleSharp; // Style of the effect.

    magSweepEff.iAttackTime = 250;               // Time to ramp up from the level of magnitude defined
                                                 // in iAttackLevel to the magnitude defined in iMagnitude
                                                 // in the beginning of the effect.

    magSweepEff.iAttackLevel = KHWRMHapticsMaxMagnitude; // Attack level ranges from KHWRMHapticsMinMagnitude 
                                                         // to KHWRMHapticsMaxMagnitude.

    magsWeepEff.iFadeTime = 250;                 // Time ramp down the effect to the level of magnitude 
                                                 // defined by iFadeLevel in the end of the effect.

    magsweepEff.iFadeLevel = 0;                  // Fade level of attack level ranges from KHWRMHapticsMinMagnitude 
                                                 // to KHWRMHapticsMaxMagnitude.

    /**
    * Playing a MagSweep effect and stopping it
    */

    // Variable whose reference is given as an argument to PlayMagSweepEffect. 
    // The reference is used to return handle for the playing effect.
    TInt magSweepHandle ( 0 );
    iHaptics->PlayMagSweepEffect( magSweepEff, magSweepHandle );

    // This delay is just an example. The effect is stopped after a delay
    TTimeIntervalMicroSeconds32 delay( 2000000 );
    User::After( delay );

    // Use the effect handle to define which effect to stop
    iHaptics->StopPlayingEffect( magSweepHandle );

    /**
    * Playing a Periodic effect and stopping all playing effects
    */

    CHWRMHaptics::THWRMHapticsPeriodicEffect periodicEff;
     
    // This example shows how to define infinite playing duration
    periodicEff.iDuration = iHaptics->InfiniteDuration();
    periodicEff.iMagnitude = KHWRMHapticsMaxMagnitude/4; // 25% of maximum
    // Struct for defining periodic effects has an extra data member that can be used 
    // to define the period of vibration in milliseconds.  
    periodicEff.iPeriod = 200;
    periodicEff.iStyle = CHWRMHaptics::EHWRMHapticsStyleSmooth;
    periodicEff.iAttackTime = 250;
    periodicEff.iAttackLevel = 0;
    periodicEff.iFadeTime = 250;
    periodicEff.iFadeLevel = 0;

    TInt periodicHandle( 0 );
    iHaptics->PlayPeriodicEffect( periodicEff, periodicHandle );

    TTimeIntervalMicroSeconds32 delay( 1000000 );
    User::After( delay );

    // There's a special API method for stopping all playing effects of
    // the client application. 
    iHaptics->StopAllPlayingEffects();
    Related APIs
    • PlayMagSweepEffect()
    • PlayPeriodicEffect()
    • THWRMHapticsEffectStyles
    • THWRMHapticsMagSweepEffect
    • THWRMHapticsPeriodicEffect

    Modifying a currently playing simple effect

    The Haptics API provides methods for modifying simple effects that are already playing. The parameters that are used to modify an effect are the same as those used to play the effect, except that the effect handle obtained from initially playing the effect is passed as an input argument to the modify method.

                  
                   /**
                   
    * Playing a MagSweep effect and modifying it.
    */
    magSweepEff.iDuration = 6000;                        // duration in milliseconds
    magSweepEff.iMagnitude = KHWRMHapticsMaxMagnitude/5; // 20% magnitude of the max magnitude.

    TInt magSweepHandle( 0 );
    haptics->PlayMagSweepEffect( magSweepEff, magSweepHandle );

    // this delay is just an example
    // effect duration was 6 secs, so wait 2 secs to allow the effect to start playing
    TTimeIntervalMicroSeconds32 delay( 2000000 ); 
    User::After( delay );

    magSweepEff.iMagnitude = KHWRMHapticsMaxMagnitude/2; // change the magnitude of the effect

    User::LeaveIfError( haptics->ModifyPlayingMagSweepEffect( magSweepHandle, magSweepEff ) );

    Streaming effects

    The streaming effect functionality is designed for using haptics with streaming media applications. When using the streaming functionality, the application periodically supplies small samples of effect data to be rendered by calling the PlayStreamingSample() method. Streaming effects allow for proper multimedia synchronization over arbitrary time spans.

                  
                   /**
                   
    * Creating a streaming effect, playing streaming samples
    * and destroying a streaming effect
    */

    // Variable whose reference is given as an argument to CreateStreamingEffect.
    // The reference is used to return a handle to the created streaming effect.
    TInt streamingHandle( 0 );
    User::LeaveIfError( iHaptics->CreateStreamingEffect( streamingHandle ) );

    ...

    // Example of a function that gets called when a new streaming sample is ready.
    void StreamingDataUpdated( const TDesC8& aData, TInt aStreamingHandle )
        {
        // PlayStreamingSample method is called with the handle obtained from creation of
        // the streaming effect above and with the new data sample
        iHaptics->PlayStreamingSample( aStreamingHandle, aData );
        }

    ...

    // Eventually the streaming effect should be destroyed to release any reserved resources.
    iHaptics->DestroyStreamingEffect( streamingHandle );
    Related APIs
    • PlayStreamingSample()

    Effect data buffers

    The Haptics API provides methods for playing effects defined in effect data buffers. An effect data buffer is a binary buffer that contains effect definitions and additional metadata relating to those effects. The buffer can contain just simple effects or simple effects and timeline effects that are constructed from those simple effects scheduled over time.

    Effect data buffers provide an alternative way of defining simple effects, besides using the Haptics API methods to programmatically create haptic effects with parameter values. The Haptics API does not provide functions to explicitly define timeline effects. Therefore the effect data buffers are the only way to present timeline effects to the Haptics API.

    There are two ways to play effects from effect data buffers. Either by directly calling a PlayEffect() variant that takes as an argument a descriptor containing the data, or by first loading the data buffer to the Haptics system ( LoadEffectFile() ) and then using a variant of PlayEffect() that does not take the data buffer as an argument but instead uses the previously loaded data. The call to LoadEffectFile() returns a file handle to the caller. The handle is then given as an argument to the play method, thus allowing the haptics system to distinguish from which loaded effect data buffer to play the effect. The example below shows both of these alternatives. Note that it is possible to load data from several data buffers into the Haptics system. The file handles returned from the LoadEffectData() call are used to distinguish between the effects defined in different loaded buffers.

    Once the data from an effect data buffer has been loaded into the Haptics system, there are methods for enquiring various attributes of the effects contained within the loaded data. The GetEffectCount() method returns the number of individual effects within the data. GetEffectType() , GetEffectDuration() and GetEffectName() methods are used (with index of the effect given as an argument) to get effect-specific information. For magnitude sweep and periodic effects, it is possible to get the whole effect definition by calling GetMagSweepEffectDefinition() or GetPeriodicEffectDefinition() . There is also a useful GetEffectIndexFromName() method that can be used to get the index of an effect within the effect data buffer from the effect's name as shown in the example below.

                  
                   /**
                   
    * Preparing to use an effect file.
    */

    RFs fs;
    CleanupClosePushL( fs );
    User::LeaveIfError( fs.Connect() );
    _LIT( KPathToEffectDataFolder, "C://SomePathTo//EffectDataFolder//" );
    fs.SetSessionPath( KPathToEffectDataFolder );

    RFile file;
    CleanupClosePushL( file );
    _LIT( KFileName, "ExampleEffectsFile" );
    User::LeaveIfError( file.Open( fs, KFileName, EFileRead ) );

    TInt fileSize( 0 );
    User::LeaveIfError( file.Size( fileSize ) );

    HBufC8* dataBuffer = HBufC8::NewLC( fileSize );
    TPtr8 readBuf = dataBuffer->Des();
    User::LeaveIfError( file.Read( readBuf ) );

    /**
    * Load effect data buffer first. Then play an effect from it.
    */

    // A variable into which a handle for the loaded data is stored. A reference to
    // this variable is given as an argument to LoadEffectFile for the Haptics to assign.
    TInt fileHandle( 0 );
    User::LeaveIfError( iHaptics->LoadEffectFile( *dataBuffer, fileHandle ) );

    TInt effectIndex( 1 );  // index of the effect inside the data that we want to play;
    TInt effectHandle( 0 ); // variable to receive the effect handle of the playing effect

    iHaptics->PlayEffect( fileHandle, effectIndex, effectHandle );

    // Often the index of an individual effect inside the data is not known beforehand. It can be queried
    // using the effect's name
    _LIT( KEffectName, "ExampleEffect" );
    User::LeaveIfError( iHaptics->GetEffectIndexFromName( fileHandle, KEffectName, effectIndex ) );
    iHaptics->PlayEffect( fileHandle, effectIndex, effectHandle );

    /**
    * Effects can also be played directly (without first loading the effect data buffer to Haptics)
    * by giving a reference to a descriptor containing the data buffer as an argument.
    */

    iHaptics->PlayEffect( *dataBuffer, effectIndex, effectHandle );

    CleanupStack::PopAndDestroy( dataBuffer );
    CleanupStack::PopAndDestroy( &file );
    CleanupStack::PopAndDestroy( &fs );
    //...
    // Eventually the loaded data should be deleted to release reserved resources
    // Note: Actually the resources are released also when client closes the haptics
    iHaptics->DeleteEffectData( fileHandle ); // or iHaptics->DeleteAllEffectData() to delete all datas
                                              // loaded by this application. 

    Note: For timeline effects there is also a method called PlayEffectRepeat() that can be used to request repeated playing of an effect. The number of repeats is given as an argument. If a timeline effect needs to be repeated infinite times, the value returned from a call to the Haptics API's InfiniteRepeat() method must be used as a repeat argument. For other types of effects than timeline effects, the repeat method plays the effect just once (i.e., for non-timeline effects this is equivalent to the normal PlayEffect() method).

    Related APIs
    • GetEffectCount()
    • GetEffectDuration()
    • GetEffectIndexFromName()
    • GetEffectName()
    • GetEffectType()
    • GetMagSweepEffectDefinition()
    • GetPeriodicEffectDefinition()
    • InfiniteRepeat()
    • LoadEffectData()
    • LoadEffectFile()
    • PlayEffect()
    • PlayEffectRepeat()

    Pausing and resuming playing of effects

    It is possible to pause an effect during its playing and then later resume the playing using the Haptics API's methods PausePlayingEffect() and ResumePausedEffect() respectively as shown in the example below. After resuming the previously paused effect, its playing is continued from the point where it was paused.

                  
                   // we have started the playing of a longish effect and have stored its handle to the effectHandle variable
                   
    // First, pause the playing of the effect
    User::LeaveIfError( iHaptics->PausePlayingEffect( effectHandle ) );

    // Then, resume the playing
    User::LeaveIfError( iHaptics->ResumePausedEffect( effectHandle ) );
    Related APIs
    • PausePlayingEffect()
    • ResumePausedEffect()
    Related APIs
    • TRequestStatus

    Error handling

    The leave mechanism and return values are used to indicate errors. Normal Symbian error handling practices should be used, including, e.g., using the cleanup stack and the TRAP harness.

    Some typical error codes:

    • KErrAccessDenied : the license key is not set or when setting the license key, the provided key is not accepted.

      A typical license key format is a 32-character-long string. Characters are encoded in 8-bytes, thus not in Unicode.

  • KErrNotSupported , when calling OpenActuatorL() with a logical actuator that is not supported by the system. This error code is also returned if trying to set or get an incompatible property or capability type.

  • KErrArgument , argument passed to a method was invalid.

  • KErrNotReady , when trying to use the Haptics API's methods before it has been properly initialized.

  • The Haptics API does not have many leaving methods as handling leaves is slow. An opportunity to do something about an error has already passed when the leave is caught in the TRAP harness.

    Related APIs
    • KErrAccessDenied
    • KErrArgument
    • KErrNotReady
    • KErrNotSupported
    • OpenActuatorL()
    • TRAP

    Memory overhead

    Using of the Haptics API can cause an additional memory overhead since a loaded effect data buffer cache is implemented in the client side. The amount of memory needed depends on the number and size of the loaded data buffers. In real life situations, the memory overhead is quite small though since the binary format of the effect data is compact and usually there are only a few effect data buffers loaded simultaneously per client. To keep the memory overhead as low as possible, the client should delete the loaded effect data buffers ( DeleteEffectData() ) whenever the data buffer becomes obsolete.

    Related APIs
    • DeleteEffectData()

    Extensions to the API

    The API does not explicitly support any kinds of extensions to it.

    Limitations of the API

    A valid license key is needed for using the Haptics API. See Nokia Developer web site ( http://www.developer.nokia.com/ ) for information how a license key can be acquired.

    Related APIs
    • CHWRMHaptics
    • EHWRMHapticsLicensekey
    • MHWRMHapticsActuatorObserver
    • MHWRMHapticsObserver
    • NewL()
    • OpenActuatorL()
    • SetDeviceProperty()
    • SupportedActuators()

    Glossary

    Abbreviations

    API Application Programming Interface

    WINS

    Windows (Visual Studio®) compilation

    WINSCW

    Windows (CodeWarrior®) compilation

    Definitions

    Haptics Haptics technology refers to technology which interfaces with the user via the sense of touch by applying forces, vibrations and/or motions to the user.

    Magnitude Sweep effect (MagSweep)

    Type of simple effect. Vibrates at a magnitude and device-dependent rate.

    Periodic effect (Periodic)

    Type of simple effect. Periodic effects allow the period or speed of vibration to be explicitly controlled independent of magnitude.

    Timeline effect

    Type of effect that consists of simple effects scheduled over time.

    Effect data buffer

    Binary data buffer that contains effect definitions. It can have simple effects only or simple effects and timeline effects constructed from those simple effects.

    Actuator

    In haptics context, an actuator refers to any kind of mechanic device that creates the physical movement in the device, e.g., Vibra.

    Haptics device capability

    Capability of an actuator, e.g., minimum and maximum period and duration of effect playing, actuator type, etc.

    Haptics device property

    Properties of the haptics system that can be set and enquired. The most essential is the license key that must be correctly set by the application in order to unlock the full functionality of the haptics system. Others include haptics instance and system-wide strength and priority settings.

    References

    None.