taskswitcher/taskswitcherui/taskswitcherapp/src/tsappui.cpp
changeset 4 4d54b72983ae
child 5 c743ef5928ba
equal deleted inserted replaced
3:fb3763350a08 4:4d54b72983ae
       
     1 /*
       
     2 * Copyright (c) 2008 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:  AppUi class
       
    15  *
       
    16 */
       
    17 
       
    18 
       
    19 #include "tsappui.h"
       
    20 #include "tsappview.h"
       
    21 #include "tsapplogging.h"
       
    22 #include "tsdevicestate.h"
       
    23 #include "tsuid.hrh"
       
    24 #include "tscommands.hrh"
       
    25 #include <akntitle.h>
       
    26 #include <hlplch.h>
       
    27 #include <avkon.rsg>
       
    28 #include <bautils.h>
       
    29 #include <AknUtils.h>
       
    30 #include <tstaskswitcher.rsg>
       
    31 #include <pslninternalcrkeys.h>
       
    32 #include <oommonitorsession.h>
       
    33 #include <hal.h>
       
    34 #include <hal_data.h>
       
    35 #include <akntranseffect.h>
       
    36 
       
    37 
       
    38 // AknCapServer UID, used for P&S category
       
    39 const TUid KTaskswitcherStateCategory = { 0x10207218 };
       
    40 
       
    41 // Taskswitcher UI, used as P&S key
       
    42 const TInt KTaskswitcherStateKey = KTsAppUidValue;
       
    43 
       
    44 // Values for Taskswitcher launching P&S
       
    45 const TInt KTaskswitcherBackgroundValue = 1;
       
    46 const TInt KTaskswitcherForegroundValue = KTaskswitcherBackgroundValue << 1;
       
    47 const TInt KTaskswitcherShortAppKeyPressed = KTaskswitcherForegroundValue << 1;
       
    48 const TInt KTaskswitcherLongAppKeyPressed = KTaskswitcherShortAppKeyPressed << 1;
       
    49 
       
    50 //short/long App key values 
       
    51 const TInt KAppKeyTypeShort = 1;
       
    52 const TInt KAppKeyTypeLong = 2;
       
    53 
       
    54 //values for checking the OOM
       
    55 const TInt KMemoryRequestAmountInBytes = 524288;
       
    56 const TInt KMinMemoryAmountInBytes = 524288;
       
    57 const TInt KMemoryToBeReservedInBytes = 524288; // 512 KB
       
    58 
       
    59 // time to wait before sending the task to background
       
    60 // (must give time to animation)
       
    61 const TInt KWaitBeforeGoingToBackground = 100000;
       
    62 
       
    63 // -----------------------------------------------------------------------------
       
    64 // CTsAppUi::ConstructL()
       
    65 // ConstructL is called by the application framework
       
    66 // -----------------------------------------------------------------------------
       
    67 //
       
    68 void CTsAppUi::ConstructL()
       
    69     {
       
    70     TSLOG_CONTEXT( CTsAppUi::ConstructL, TSLOG_LOCAL );
       
    71     TSLOG_IN();
       
    72 
       
    73 #ifdef _DEBUG
       
    74     // create log folder
       
    75 	_LIT( KLogPath, "c:\\logs\\taskswitcher\\" );
       
    76 	RFs fs;
       
    77 	if ( fs.Connect() == KErrNone )
       
    78 		{
       
    79 		fs.MkDirAll( KLogPath );
       
    80 		fs.Close();
       
    81 		}
       
    82 #endif
       
    83 
       
    84     // Initialise app UI with standard value.
       
    85     BaseConstructL( CAknAppUi::EAknEnableSkin | CAknAppUi::EAknEnableMSK );
       
    86 
       
    87 #ifndef _DEBUG
       
    88     // set as system application (in release build) so we never get closed
       
    89     iEikonEnv->SetSystem( ETrue );
       
    90 #endif
       
    91 
       
    92     //Initialize effects change observation
       
    93     iThemeEffectsEnabledWatcher =
       
    94         CTsCenrepListener::NewL( KCRUidThemes, KThemesTransitionEffects, *this );
       
    95     CenrepChanged( KThemesTransitionEffects, iThemeEffectsEnabledWatcher->Value() );
       
    96     
       
    97     // Hide status pane
       
    98     StatusPane()->MakeVisible( EFalse );
       
    99 
       
   100     // Change CBA if needed, default is non-touch in rss
       
   101     if ( AknLayoutUtils::PenEnabled() )
       
   102         {
       
   103         Cba()->SetCommandSetL( R_TS_CBA_TOUCH );
       
   104         }
       
   105     Cba()->MakeVisible(EFalse);
       
   106 
       
   107     // Create timer
       
   108     iGoToBackgroundTimer = CPeriodic::NewL( CActive::EPriorityStandard );
       
   109 
       
   110     // Create commonly used instances (device state only?)
       
   111     iDeviceState = CTsDeviceState::NewL();
       
   112 
       
   113     // Create UI
       
   114     iAppView = CTsAppView::NewL( ApplicationRect(), *iDeviceState );
       
   115     AddToStackL( iAppView );
       
   116     
       
   117     //Enable effects
       
   118     GfxTransEffect::Enable();
       
   119     GfxTransEffect::Register(iAppView,TUid::Uid(KTsAppUidValue));
       
   120     GfxTransEffect::SetTransitionObserver(this);
       
   121 
       
   122     // Listen for change in the value of the ts state property.
       
   123     iPropListener = new ( ELeave ) CTsPropertyListener(
       
   124             KTaskswitcherStateCategory, KTaskswitcherStateKey, *this );
       
   125 
       
   126     // Initialise the application task object with the window group id of
       
   127     // our application ( so that it represent our app )
       
   128     iApplicationTask.SetWgId( iCoeEnv->RootWin().Identifier() );
       
   129 
       
   130     // And finally, go to background.
       
   131     MoveAppToBackground( AknTransEffect::ENone );
       
   132 
       
   133     TSLOG_OUT();
       
   134     }
       
   135 
       
   136 // -----------------------------------------------------------------------------
       
   137 // CTsAppUi::CTsAppUi()
       
   138 // Perform the first phase of two phase construction
       
   139 // -----------------------------------------------------------------------------
       
   140 //
       
   141 CTsAppUi::CTsAppUi(): iForeground( ETrue ),
       
   142                                       iApplicationTask( iCoeEnv->WsSession() )
       
   143     {
       
   144     // no implementation required
       
   145     }
       
   146 
       
   147 // -----------------------------------------------------------------------------
       
   148 // CTsAppUi::~CTsAppUi()
       
   149 // Destructor
       
   150 // -----------------------------------------------------------------------------
       
   151 //
       
   152 CTsAppUi::~CTsAppUi()
       
   153     {
       
   154     if( GfxTransEffect::IsRegistered( iAppView ) )
       
   155         {
       
   156         GfxTransEffect::Deregister(iAppView);
       
   157         
       
   158         }
       
   159     GfxTransEffect::SetTransitionObserver(0);
       
   160     
       
   161     delete iGoToBackgroundTimer;
       
   162     delete iPropListener;
       
   163 
       
   164     // destroy UI first
       
   165     if ( iAppView )
       
   166         {
       
   167         RemoveFromStack( iAppView );
       
   168         delete iAppView;
       
   169         }
       
   170 
       
   171     delete iDeviceState;
       
   172     delete iMemAllocBuf;
       
   173     delete iThemeEffectsEnabledWatcher;
       
   174     }
       
   175 
       
   176 // -----------------------------------------------------------------------------
       
   177 // CTsAppView::EffectsEnabled
       
   178 // -----------------------------------------------------------------------------
       
   179 //
       
   180 TBool CTsAppUi::EffectsEnabled() const
       
   181     {
       
   182     return iEffectsEnabled;
       
   183     }
       
   184 
       
   185 // -----------------------------------------------------------------------------
       
   186 // CTsAppUi::StartTransion
       
   187 // -----------------------------------------------------------------------------
       
   188 //
       
   189 void CTsAppUi::StartTransion( TUint aTransitionType )
       
   190     {
       
   191     if( !EffectsEnabled() )
       
   192         {
       
   193         return;
       
   194         }
       
   195     switch(aTransitionType)
       
   196         {
       
   197     case AknTransEffect::EApplicationStart:
       
   198         StartTransition( aTransitionType, 
       
   199                          ETrue, 
       
   200                          EFalse, 
       
   201                          CAknTransitionUtils::EForceVisible);
       
   202         break;
       
   203     case AknTransEffect::EApplicationExit:
       
   204         StartTransition( aTransitionType, 
       
   205                          EFalse, 
       
   206                          EFalse, 
       
   207                          CAknTransitionUtils::EForceInvisible );
       
   208         break;
       
   209     case AknTransEffect::EApplicationStartRect:
       
   210         StartTransition( aTransitionType, 
       
   211                          EFalse, 
       
   212                          ETrue, 
       
   213                          CAknTransitionUtils::EForceInvisible );
       
   214         break;
       
   215         }
       
   216     }
       
   217 
       
   218 // -----------------------------------------------------------------------------
       
   219 // CTsAppUi::StartTransition
       
   220 // -----------------------------------------------------------------------------
       
   221 //
       
   222 void CTsAppUi::StartTransition( TUint aTranstionId,
       
   223                                 TBool aVisibility,
       
   224                                 TBool /*aLayers*/, 
       
   225                                 TUint aSubCom )
       
   226     {
       
   227     const TDesC8* ptr = reinterpret_cast<const TDesC8*>(iAppView);
       
   228     GfxTransEffect::Abort(iAppView);
       
   229     GfxTransEffect::Begin( iAppView, aTranstionId );
       
   230     GfxTransEffect::SetDemarcation( iAppView, iAppView->Rect() );
       
   231     GfxTransEffect::NotifyExternalState( ECaptureComponentsBegin, ptr );
       
   232     iAppView->MakeVisible( aVisibility );
       
   233     CAknTransitionUtils::MakeVisibleSubComponents( 
       
   234         iAppView,
       
   235         static_cast<CAknTransitionUtils::TMakeVisibleSubComponentsInfo>(aSubCom) );
       
   236     GfxTransEffect::NotifyExternalState( ECaptureComponentsEnd, ptr );
       
   237     GfxTransEffect::End( iAppView );
       
   238     }
       
   239 
       
   240 // -----------------------------------------------------------------------------
       
   241 // CTsAppUi::TransitionFinished
       
   242 // -----------------------------------------------------------------------------
       
   243 //
       
   244 void CTsAppUi::TransitionFinished(const CCoeControl* /*aControl*/, 
       
   245                                   TUint /*aAction*/)
       
   246     {
       
   247     /*if( aControl == iAppView )
       
   248         {
       
   249 		@TODO IMPLEMENT
       
   250         }*/
       
   251     }
       
   252 
       
   253 // -----------------------------------------------------------------------------
       
   254 // CTsAppUi::HandleCommandL()
       
   255 // Takes care of command handling.
       
   256 // -----------------------------------------------------------------------------
       
   257 //
       
   258 void CTsAppUi::HandleCommandL( TInt aCommand )
       
   259     {
       
   260     switch ( aCommand )
       
   261         {
       
   262         case EAknCmdExit:
       
   263         case EEikCmdExit:
       
   264             Exit();
       
   265             break;
       
   266 
       
   267         case EAknSoftkeyExit:
       
   268         case EAknSoftkeyBack:
       
   269             // RSK => just hide
       
   270             MoveAppToBackground( AknTransEffect::EApplicationExit );
       
   271             break;
       
   272 
       
   273         case ETsCmdHelp:
       
   274             {
       
   275             MoveAppToBackground( AknTransEffect::EApplicationExit );
       
   276             CArrayFix<TCoeHelpContext>* buf = CCoeAppUi::AppHelpContextL();
       
   277             HlpLauncher::LaunchHelpApplicationL( iCoeEnv->WsSession(), buf );
       
   278             }
       
   279             break;
       
   280 
       
   281         case EAknSoftkeySelect:
       
   282             {
       
   283             // select is generated by lsk and msk (see the resource file)
       
   284             // Simulate a middle key press to the controls.
       
   285             // Note that SimulateKeyEventL must not be used here or else it
       
   286             // will end up in an infinite loop.
       
   287             TKeyEvent keyEvent;
       
   288             keyEvent.iCode = EKeyOK;
       
   289             keyEvent.iScanCode = EStdKeyDevice3;
       
   290             keyEvent.iModifiers = keyEvent.iRepeats = 0;
       
   291             iAppView->OfferKeyEventL( keyEvent, EEventKeyDown );
       
   292             iAppView->OfferKeyEventL( keyEvent, EEventKey );
       
   293             iAppView->OfferKeyEventL( keyEvent, EEventKeyUp );
       
   294             }
       
   295             break;
       
   296 
       
   297         default:
       
   298             break;
       
   299         }
       
   300     }
       
   301 
       
   302 // -----------------------------------------------------------------------------
       
   303 // CTsAppUi::HandleForegroundEventL
       
   304 // Called by the system when the app is moved to foreground or background.
       
   305 // -----------------------------------------------------------------------------
       
   306 //
       
   307 void CTsAppUi::HandleForegroundEventL( TBool aForeground )
       
   308     {
       
   309     TSLOG_CONTEXT( HandleForegroundEventL, TSLOG_LOCAL );
       
   310     TSLOG1_IN( "aForeground = %d", aForeground );
       
   311 
       
   312     // These calls may be redundant but the functions will do nothing if the
       
   313     // state has already been changed.
       
   314     // Both this function and the 'manual' MoveAppTo functions must fire the events
       
   315     // because in some cases only one of them will run (e.g. when bringing to foreground
       
   316     // not with the hw key but by other means etc.)
       
   317     if ( aForeground )
       
   318         {
       
   319         HandleSwitchToForegroundEvent();
       
   320         }
       
   321     else
       
   322         {
       
   323         HandleSwitchToBackgroundEvent();
       
   324         }
       
   325 
       
   326     // Call Base class method
       
   327     CAknAppUi::HandleForegroundEventL( aForeground );
       
   328 
       
   329     TSLOG_OUT();
       
   330     }
       
   331 
       
   332 // -----------------------------------------------------------------------------
       
   333 // CTsAppUi::PropertyChanged
       
   334 // -----------------------------------------------------------------------------
       
   335 //
       
   336 void CTsAppUi::PropertyChanged( TUid aCategory, TUint aKey )
       
   337     {
       
   338     TSLOG_CONTEXT( PropertyChanged, TSLOG_LOCAL );
       
   339     TSLOG_IN();
       
   340 
       
   341     TInt value( 0 );
       
   342 
       
   343     if ( RProperty::Get( aCategory, aKey, value ) == KErrNone )
       
   344         {
       
   345         if ( iForeground && (value & KTaskswitcherBackgroundValue) )
       
   346             {
       
   347             MoveAppToBackground( AknTransEffect::EApplicationExit );
       
   348             }
       
   349         else if ( !iForeground && (value & KTaskswitcherForegroundValue) )
       
   350             {
       
   351             MoveAppToForeground( AknTransEffect::EApplicationStart );
       
   352             }
       
   353         else if( value & KTaskswitcherLongAppKeyPressed )
       
   354             {
       
   355             if(!iForeground)
       
   356                 {
       
   357                 MoveAppToBackground( AknTransEffect::EApplicationExit );
       
   358                 }
       
   359             else
       
   360                 {
       
   361                 iAppView->HandleAppKey(KAppKeyTypeLong);
       
   362                 }
       
   363             }
       
   364         else if(  value & KTaskswitcherShortAppKeyPressed )
       
   365             {
       
   366             iAppView->HandleAppKey(KAppKeyTypeShort);
       
   367             }
       
   368         }
       
   369 
       
   370     TSLOG_OUT();
       
   371     }
       
   372 
       
   373 // -----------------------------------------------------------------------------
       
   374 // CTsAppUi::HandleResourceChangeL
       
   375 // -----------------------------------------------------------------------------
       
   376 //
       
   377 void CTsAppUi::HandleResourceChangeL( TInt aType )
       
   378     {
       
   379     // Must call base class implementation first,
       
   380     // sizes from LayoutMetricsRect etc. will only be correct after this.
       
   381     CAknAppUi::HandleResourceChangeL( aType );
       
   382     if( aType == KEikDynamicLayoutVariantSwitch && iAppView )
       
   383         {
       
   384         iAppView->SetRect( ApplicationRect() );
       
   385         }
       
   386     // forward event
       
   387     iDeviceState->HandleResourceChange( aType );
       
   388     iAppView->HandleResourceChange( aType );
       
   389     }
       
   390 
       
   391 // -----------------------------------------------------------------------------
       
   392 // CTsAppUi::MoveAppToBackground()
       
   393 // -----------------------------------------------------------------------------
       
   394 //
       
   395 void CTsAppUi::MoveAppToBackground( TUint aTransitionType )
       
   396     {
       
   397     TSLOG_CONTEXT( MoveAppToBackground, TSLOG_LOCAL );
       
   398     TSLOG_IN();
       
   399 
       
   400     if ( AknTransEffect::ENone == aTransitionType || !EffectsEnabled() )
       
   401         {
       
   402         GoToBackgroundTimerCallback( this );
       
   403         }
       
   404     else
       
   405         {
       
   406         StartTransion(AknTransEffect::EApplicationExit);
       
   407         iGoToBackgroundTimer->Cancel();
       
   408         iGoToBackgroundTimer->Start( 
       
   409                 KWaitBeforeGoingToBackground, 
       
   410                 0,
       
   411                 TCallBack( GoToBackgroundTimerCallback, this ) );
       
   412         }
       
   413     TSLOG_OUT();
       
   414     }
       
   415 
       
   416 // -----------------------------------------------------------------------------
       
   417 // CTsAppUi::CenrepChanged
       
   418 // -----------------------------------------------------------------------------
       
   419 //
       
   420 void CTsAppUi::CenrepChanged( TUint32 /*aKey*/, TInt aNewValue )
       
   421     {
       
   422     iEffectsEnabled = !(aNewValue & AknTransEffect::EFullScreenTransitionsOff);
       
   423     }
       
   424 
       
   425 // -----------------------------------------------------------------------------
       
   426 // CTsAppUi::GoToBackgroundTimerCallback
       
   427 // -----------------------------------------------------------------------------
       
   428 //
       
   429 TInt CTsAppUi::GoToBackgroundTimerCallback( TAny* aParam )
       
   430     {
       
   431     CTsAppUi* self = static_cast<CTsAppUi*>( aParam );
       
   432     if ( self->iGoToBackgroundTimer )
       
   433         {
       
   434         self->iGoToBackgroundTimer->Cancel();
       
   435         }
       
   436 
       
   437     // Request window server to bring our application
       
   438     // to background
       
   439     self->iApplicationTask.SendToBackground();
       
   440 
       
   441     // Notify
       
   442     self->HandleSwitchToBackgroundEvent();
       
   443 
       
   444     return 0;
       
   445     }
       
   446 
       
   447 // -----------------------------------------------------------------------------
       
   448 // CTsAppUi::MoveAppToForeground()
       
   449 // -----------------------------------------------------------------------------
       
   450 //
       
   451 void CTsAppUi::MoveAppToForeground( TUint  /*aTransitionType*/ )
       
   452     {
       
   453     TSLOG_CONTEXT( MoveAppToForeground, TSLOG_LOCAL );
       
   454     TSLOG_IN();
       
   455 
       
   456     // Request window server to bring our application
       
   457     // to foreground
       
   458     iApplicationTask.BringToForeground();
       
   459 
       
   460     // Notify
       
   461     HandleSwitchToForegroundEvent();
       
   462 
       
   463     TSLOG_OUT();
       
   464     }
       
   465 
       
   466 // -----------------------------------------------------------------------------
       
   467 // CTsAppUi::HandleSwitchToBackgroundEvent
       
   468 // -----------------------------------------------------------------------------
       
   469 //
       
   470 void CTsAppUi::HandleSwitchToBackgroundEvent()
       
   471     {
       
   472     TSLOG_CONTEXT( HandleSwitchToBackgroundEvent, TSLOG_LOCAL );
       
   473     TSLOG_IN();
       
   474 
       
   475     // must not do anything if iForeground is already up-to-date
       
   476     // exclude cases with dialogs like power menu, memory card
       
   477     if( iForeground && !IsFaded() )  
       
   478         {
       
   479         iForeground = EFalse;
       
   480         SetTaskswitcherStateProperty( KTaskswitcherBackgroundValue );
       
   481 
       
   482         //allocating extra memory space
       
   483         if ( !iMemAllocBuf )
       
   484             {
       
   485             iMemAllocBuf =
       
   486                 (TUint8*) User::Alloc( KMemoryToBeReservedInBytes );
       
   487             }
       
   488 
       
   489         // notify view
       
   490         iAppView->HandleSwitchToBackgroundEvent();
       
   491         }
       
   492 
       
   493     TSLOG_OUT();
       
   494     }
       
   495 
       
   496 // -----------------------------------------------------------------------------
       
   497 // CTsAppUi::HandleSwitchToForegroundEvent
       
   498 // -----------------------------------------------------------------------------
       
   499 //
       
   500 void CTsAppUi::HandleSwitchToForegroundEvent()
       
   501     {
       
   502     TSLOG_CONTEXT( HandleSwitchToForegroundEvent, TSLOG_LOCAL );
       
   503     TSLOG_IN();
       
   504 
       
   505     // must not do anything if iForeground is already up-to-date
       
   506     if ( !iForeground )
       
   507         {
       
   508         //freeing extra memory space
       
   509         delete iMemAllocBuf;
       
   510         iMemAllocBuf = NULL;
       
   511 
       
   512         TInt freeRamMemory;
       
   513         HAL::Get( HALData::EMemoryRAMFree, freeRamMemory );
       
   514         if ( freeRamMemory <= KMinMemoryAmountInBytes )
       
   515             {
       
   516             FreeMemoryRequest();
       
   517             }
       
   518 
       
   519         iForeground = ETrue;
       
   520         SetTaskswitcherStateProperty( KTaskswitcherForegroundValue );
       
   521 
       
   522         // notify view
       
   523         iAppView->HandleSwitchToForegroundEvent();
       
   524         }
       
   525 
       
   526     TSLOG_OUT();
       
   527     }
       
   528 
       
   529 // -----------------------------------------------------------------------------
       
   530 // CTsAppUi::SetTaskswitcherShowProperty
       
   531 // -----------------------------------------------------------------------------
       
   532 //
       
   533 void CTsAppUi::SetTaskswitcherStateProperty( TInt aValue )
       
   534     {
       
   535     TSLOG_CONTEXT( CTsAppUi::SetTaskswitcherShowProperty, TSLOG_LOCAL );
       
   536     TSLOG_IN();
       
   537 
       
   538     if ( RProperty::Set(
       
   539             KTaskswitcherStateCategory, KTaskswitcherStateKey, aValue ) != KErrNone )
       
   540         {
       
   541         TInt error = RProperty::Define(
       
   542                 KTaskswitcherStateCategory, KTaskswitcherStateKey, RProperty::EInt );
       
   543         if ( error != KErrNone )
       
   544             {
       
   545             TSLOG1( TSLOG_INFO, "RProperty::Define Error: %d", error );
       
   546             }
       
   547 
       
   548         error = RProperty::Set( KTaskswitcherStateCategory, KTaskswitcherStateKey, aValue );
       
   549         if ( error != KErrNone )
       
   550             {
       
   551             TSLOG1( TSLOG_INFO, "RProperty::Set Error: %d", error );
       
   552             }
       
   553         }
       
   554 
       
   555     TSLOG_OUT();
       
   556     }
       
   557 
       
   558 // -----------------------------------------------------------------------------
       
   559 // CTsAppUi::FreeMemoryRequest
       
   560 // -----------------------------------------------------------------------------
       
   561 //
       
   562 void CTsAppUi::FreeMemoryRequest()
       
   563     {
       
   564     TSLOG_CONTEXT( CTsAppUi::FreeMemoryRequest, TSLOG_LOCAL );
       
   565     TSLOG_IN();
       
   566     ROomMonitorSession oomMs;
       
   567     TInt error = oomMs.Connect();
       
   568     if ( error != KErrNone)
       
   569         {
       
   570         TSLOG1( TSLOG_INFO, "Could not connect to ROomMonitorSession, %d", error );
       
   571         }
       
   572     else
       
   573         {
       
   574         oomMs.RequestFreeMemory( KMemoryRequestAmountInBytes );
       
   575         oomMs.Close();
       
   576         }
       
   577     TSLOG_OUT();
       
   578     }
       
   579 
       
   580 
       
   581 // End of file