tactilefeedback/tactilefeedbackresolver/src/tactilefeedback.cpp
changeset 0 d54f32e146dd
equal deleted inserted replaced
-1:000000000000 0:d54f32e146dd
       
     1 /*
       
     2 * Copyright (c) 2007-2009 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:  Client side of Tactile Feedback server.
       
    15 * Part of:      Tactile Feedback.
       
    16 *
       
    17 */
       
    18 
       
    19 #include <e32base.h>
       
    20 #include <e32std.h>
       
    21 #include <ecom/ecom.h>
       
    22 #include <e32debug.h>
       
    23 
       
    24 #include <tactilefeedback.h>
       
    25 
       
    26 #include "tactilefeedbacktrace.h"
       
    27 #include "tactilefeedbacksrv.h"
       
    28 #include "tactilefeedbackdefs.h"
       
    29 
       
    30 /**
       
    31  * Own active scheduler class. We need this so that we can override the
       
    32  * CActiveScheduler::Error -function and avoid panic in case something
       
    33  * leaves.
       
    34  */
       
    35 NONSHARABLE_CLASS( CTactileScheduler ): public CActiveScheduler
       
    36     {
       
    37 public:   
       
    38 
       
    39     /**
       
    40      * This is called when something leaves in our Feedback Player
       
    41      * thread.
       
    42      */
       
    43     void Error( TInt aError ) const;
       
    44     };
       
    45 
       
    46 
       
    47 void CTactileScheduler::Error( TInt aError ) const
       
    48     {
       
    49     (void) aError; // Remove compiler warning in armv5 urel
       
    50     
       
    51     TRACE2( "CTactileScheduler::Error, aError = %d", aError );
       
    52     }
       
    53 
       
    54 /**
       
    55  * Structure for the parameters, that are passed to Feedback Player Thread
       
    56  * when it is created.
       
    57  */
       
    58 struct TTactileThreadParams
       
    59     {
       
    60     RThread* iOwningThread;
       
    61     TInt iQueueHandle;
       
    62     };
       
    63     
       
    64 /**
       
    65  * Class for creating new thread for Tactile Feedback playing, and
       
    66  * for passing feedback requests to the thread via a message queue.
       
    67  */
       
    68 NONSHARABLE_CLASS( CThreadPlayer ): public CBase
       
    69     {
       
    70 public:
       
    71     static CThreadPlayer* NewL();
       
    72     ~CThreadPlayer();
       
    73 
       
    74 private:
       
    75     CThreadPlayer() {};
       
    76     
       
    77     void ConstructL();
       
    78     
       
    79     static void RunThreadL( TAny* aParam );
       
    80 
       
    81     static TInt ThreadEntryPoint( TAny* aParam );
       
    82 
       
    83     RThread                 iThread;
       
    84     };    
       
    85 
       
    86 // ---------------------------------------------------------------------------
       
    87 // Here we create and start new thread for Tactile Feedback Playing.
       
    88 //
       
    89 // If this function returns succesfully, then the new thread was created ok
       
    90 // and is now running. Otherwise we leave from here.
       
    91 //
       
    92 // ---------------------------------------------------------------------------
       
    93 //
       
    94 void CThreadPlayer::ConstructL()
       
    95     {
       
    96     TRACE("CThreadPlayer::ConstructL - Begin");
       
    97     
       
    98     RThread thisThread;
       
    99 
       
   100     CleanupClosePushL( thisThread );
       
   101     
       
   102     TTactileThreadParams params;
       
   103     params.iOwningThread = &thisThread;
       
   104  
       
   105     User::LeaveIfError( 
       
   106         iThread.Create( 
       
   107             KTactileThreadName, 
       
   108             ThreadEntryPoint,
       
   109             KPlayerThreadStackSize, 
       
   110             KPlayerThreadHeapMinSize, 
       
   111             KPlayerThreadHeapMaxSize,
       
   112             &params, 
       
   113             EOwnerProcess ) );       
       
   114                         
       
   115     // With EPriorityMore feedback player thread operates with the same
       
   116     // priority as window server main thread. This seems to be the best
       
   117     // choice for now, as this way neither drawing or feedback can cause
       
   118     // significant delay for each other.
       
   119     iThread.SetPriority( EPriorityMore );
       
   120     iThread.Resume();
       
   121     
       
   122     // We have to wait so that our thread has read the parameters
       
   123     TRequestStatus status;
       
   124     iThread.Rendezvous( status );
       
   125     User::WaitForRequest( status );
       
   126     
       
   127     // Store thread exit type while we still have handles open
       
   128     TExitType exitType = iThread.ExitType(); 
       
   129 
       
   130     // Close thread handle to ourself.  
       
   131     CleanupStack::PopAndDestroy( &thisThread ); 
       
   132     
       
   133     // Check that rendezvouz succeeded, and that thread is still alive
       
   134     if ( exitType != EExitPending || status != KErrNone )
       
   135         {
       
   136         TRACE3("CThreadPlayer::ConstructL - Thread creation failed, %d, %d", exitType, status.Int() );
       
   137         
       
   138         User::Leave( KErrGeneral );
       
   139         }
       
   140     
       
   141     TRACE("CThreadPlayer::ConstructL - End");
       
   142     }
       
   143 
       
   144 // ---------------------------------------------------------------------------
       
   145 //
       
   146 // ---------------------------------------------------------------------------
       
   147 //
       
   148 CThreadPlayer* CThreadPlayer::NewL()
       
   149     {
       
   150     CThreadPlayer* self = new( ELeave ) CThreadPlayer();
       
   151     CleanupStack::PushL( self );
       
   152     self->ConstructL();
       
   153     CleanupStack::Pop( self );
       
   154     return self;
       
   155     }
       
   156 
       
   157 // ---------------------------------------------------------------------------
       
   158 // We close our player thread by sending an exit request and waiting for
       
   159 // the thread to close itself. This way all resources get closed cleanly.
       
   160 //
       
   161 // In case message queue is full, then we'll just kill the thread.
       
   162 // ---------------------------------------------------------------------------
       
   163 //
       
   164 CThreadPlayer::~CThreadPlayer()
       
   165     {
       
   166     if ( iThread.Handle() )
       
   167         {
       
   168         TExitType exitType = iThread.ExitType(); 
       
   169         
       
   170         if ( exitType == EExitPending )
       
   171             {
       
   172             iThread.Kill( KErrAbort );
       
   173             }
       
   174             
       
   175         iThread.Close();
       
   176         }
       
   177     }
       
   178     
       
   179 // ---------------------------------------------------------------------------
       
   180 // Rest of the actions required for setting Tactile Feedback Player thread
       
   181 // up and running (this is called from ThreadEntryPoint)
       
   182 //
       
   183 // #1 Create and install an active scheduler
       
   184 // #2 Create server instance.
       
   185 // #3 Notify main thread that we are ready to run (this allows main thread 
       
   186 //    to continue).
       
   187 // #4 Start the scheduler. Excecution will halt here in this functio until
       
   188 //    somebody stops the scheduler.
       
   189 //
       
   190 // #5 Delete server and scheduler (at this point we are exiting our thread 
       
   191 //    already).
       
   192 //
       
   193 // #6 Close ECom session, as we are now exiting the thread (this is on our
       
   194 //    responsibility even though we are not directly using Ecom).
       
   195 // ---------------------------------------------------------------------------
       
   196 //
       
   197 void CThreadPlayer::RunThreadL( TAny* /*aParam*/ )
       
   198     {
       
   199     // #1
       
   200     CTactileScheduler* s = new(ELeave) CTactileScheduler;
       
   201     CleanupStack::PushL(s);
       
   202     CActiveScheduler::Install(s);
       
   203 
       
   204     // #2
       
   205     CTactileFeedbackSrv* svr = CTactileFeedbackSrv::NewL();
       
   206 
       
   207     // #3
       
   208     RThread me;
       
   209     me.Rendezvous( KErrNone ); 
       
   210     
       
   211     // #4    
       
   212     CActiveScheduler::Start();
       
   213 
       
   214     // #5
       
   215     delete svr;
       
   216     CleanupStack::PopAndDestroy( s );
       
   217 
       
   218     // #6
       
   219     REComSession::FinalClose();
       
   220     }
       
   221         
       
   222 // ---------------------------------------------------------------------------
       
   223 // This is the entry point of Tactile feedback player thread.
       
   224 //
       
   225 // Standard operation: Create cleanup stack and call rest of the code under
       
   226 // trap harness.
       
   227 // ---------------------------------------------------------------------------
       
   228 //
       
   229 TInt CThreadPlayer::ThreadEntryPoint( TAny* aParam )
       
   230     {
       
   231     __UHEAP_MARK;
       
   232     CTrapCleanup* cleanup = CTrapCleanup::New();
       
   233     TInt err( KErrNoMemory );
       
   234     if ( cleanup )
       
   235         {
       
   236         TRAP( err, CThreadPlayer::RunThreadL( aParam ) );
       
   237         delete cleanup;
       
   238         }
       
   239     __UHEAP_MARKEND;
       
   240     return err;
       
   241     }    
       
   242     
       
   243 // --------------------------------------------------------------------------
       
   244 // Default constructor.
       
   245 // 
       
   246 // --------------------------------------------------------------------------
       
   247 //       
       
   248 EXPORT_C RTactileFeedback::RTactileFeedback() 
       
   249     {
       
   250     }
       
   251 
       
   252 // --------------------------------------------------------------------------
       
   253 // 
       
   254 // Creates connection to server
       
   255 // --------------------------------------------------------------------------
       
   256 //
       
   257 EXPORT_C TInt RTactileFeedback::Connect()
       
   258     {
       
   259     TInt ret = CreateSession( KTactileFeedbackServer, Version() );
       
   260     if (  ret != KErrNone )
       
   261         {
       
   262         TRAP( ret, iThread = CThreadPlayer::NewL() );
       
   263         if ( ret == KErrNone )
       
   264             {
       
   265             ret = CreateSession( KTactileFeedbackServer, Version() );    
       
   266             }        
       
   267         }
       
   268     
       
   269     return ret; 
       
   270     }
       
   271     
       
   272 // --------------------------------------------------------------------------
       
   273 // 
       
   274 // --------------------------------------------------------------------------
       
   275 //      
       
   276 EXPORT_C void RTactileFeedback::Close()
       
   277     {
       
   278     delete iThread;
       
   279     iThread = NULL;
       
   280     // close session    
       
   281     RSessionBase::Close();
       
   282     }    
       
   283 
       
   284 // --------------------------------------------------------------------------
       
   285 // 
       
   286 // --------------------------------------------------------------------------
       
   287 //     
       
   288 EXPORT_C void RTactileFeedback::PlayFeedback( TTouchLogicalFeedback aFeedbackType,
       
   289                                               TBool aPlayVibra,
       
   290                                               TBool aPlayAudio )
       
   291     {
       
   292     SendReceive( EPlayFeedback, TIpcArgs( aFeedbackType, 
       
   293                                           aPlayVibra, 
       
   294                                           aPlayAudio ) );    
       
   295     }
       
   296 
       
   297 // --------------------------------------------------------------------------
       
   298 // 
       
   299 // --------------------------------------------------------------------------
       
   300 //    
       
   301 EXPORT_C void RTactileFeedback::StartFeedback( TTouchContinuousFeedback aType,
       
   302                                               TInt aIntensity )
       
   303     {
       
   304     TRACE("RTactileFeedback::StartFeedback");
       
   305     SendReceive( EStartFeedback, TIpcArgs( aType, aIntensity ) );
       
   306     }
       
   307         
       
   308 // ---------------------------------------------------------------------------
       
   309 // 
       
   310 // ---------------------------------------------------------------------------
       
   311 //                        
       
   312 EXPORT_C void RTactileFeedback::ModifyFeedback( TInt aIntensity )
       
   313     {
       
   314     TRACE("RTactileFeedback::ModifyFeedback");
       
   315     SendReceive( EModifyFeedback, TIpcArgs( aIntensity ) );
       
   316     }
       
   317     
       
   318 // ---------------------------------------------------------------------------
       
   319 // 
       
   320 // ---------------------------------------------------------------------------
       
   321 //    
       
   322 EXPORT_C void RTactileFeedback::StopFeedback()
       
   323     {
       
   324     TRACE("RTactileFeedback::StopFeedback");
       
   325     SendReceive( EStopFeedback );   
       
   326     }
       
   327     
       
   328 // ---------------------------------------------------------------------------
       
   329 // 
       
   330 // ---------------------------------------------------------------------------
       
   331 //    
       
   332 EXPORT_C TInt RTactileFeedback::SetFeedbackEnabledForDevice( TTouchFeedbackType aFeedbackType )
       
   333     {
       
   334     TRACE("RTactileFeedback::StopFeedback");
       
   335     return SendReceive( ESetFBEnabledDevice, TIpcArgs( aFeedbackType ) );   
       
   336     }    
       
   337     
       
   338 // ---------------------------------------------------------------------------
       
   339 // 
       
   340 // ---------------------------------------------------------------------------
       
   341 //        
       
   342 EXPORT_C void RTactileFeedback::FeedbackEnabledForDevice( TTouchFeedbackType& aFeedbackEnabled )
       
   343     {
       
   344     TPckg<TTouchFeedbackType> enabled( aFeedbackEnabled );
       
   345     SendReceive( EFBEnabledForDevice, TIpcArgs( &enabled ) );
       
   346     }
       
   347 
       
   348 // --------------------------------------------------------------------------
       
   349 // 
       
   350 // --------------------------------------------------------------------------
       
   351 //     
       
   352 EXPORT_C void RTactileFeedback::PlayPreviewFeedback( TInt aLevel,
       
   353                                  TTouchLogicalFeedback aFeedback,
       
   354                                  TTouchFeedbackType aType )
       
   355     {
       
   356     SendReceive( EPlayPreviewFeedback, TIpcArgs( aLevel, 
       
   357                                                  aFeedback, 
       
   358                                                  aType ) );    
       
   359     }
       
   360 
       
   361 // --------------------------------------------------------------------------
       
   362 // 
       
   363 // --------------------------------------------------------------------------
       
   364 //     
       
   365 EXPORT_C void RTactileFeedback::StartPreviewFeedback( TInt aLevel,
       
   366                                   TTouchContinuousFeedback aFeedback,
       
   367                                   TInt aIntensity,
       
   368                                   TTouchFeedbackType aType )
       
   369     {
       
   370     SendReceive( EStartPreviewFeedback, TIpcArgs( aLevel, aFeedback, 
       
   371                                                   aIntensity, aType ) );
       
   372     }
       
   373 
       
   374 // --------------------------------------------------------------------------
       
   375 // 
       
   376 // --------------------------------------------------------------------------
       
   377 //     
       
   378 EXPORT_C void RTactileFeedback::ModifyPreviewFeedback( TInt aIntensity )
       
   379     {
       
   380     SendReceive( EModifyPreviewFeedback, TIpcArgs( aIntensity ) );
       
   381     }
       
   382 
       
   383 // --------------------------------------------------------------------------
       
   384 // 
       
   385 // --------------------------------------------------------------------------
       
   386 // 
       
   387 EXPORT_C void RTactileFeedback::StopPreviewFeedback()
       
   388     {
       
   389     SendReceive( EStopPreviewFeedback );    
       
   390     }
       
   391 
       
   392 
       
   393 // --------------------------------------------------------------------------
       
   394 // 
       
   395 // --------------------------------------------------------------------------
       
   396 //      
       
   397 TVersion RTactileFeedback::Version() const
       
   398     {
       
   399     return TVersion( KTactileFeedbackServerMajor, 
       
   400                      KTactileFeedbackServerMinor, 
       
   401                      KTactileFeedbackServerBuild );
       
   402     }    
       
   403