camerauis/cameraapp/generic/src/audioplayer/camaudioplayercontroller.cpp
changeset 0 1ddebce53859
child 20 38fb6f7eacd5
equal deleted inserted replaced
-1:000000000000 0:1ddebce53859
       
     1 /*
       
     2 * Copyright (c) 2007 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:  Implementation of Controller for Sound / Tone Wrappers
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 // ===========================================================================  
       
    21 // includes
       
    22 #include <e32base.h>
       
    23 #include <aknappui.h>       // CAknAppUi
       
    24 #include <aknsoundsystem.h> // CAknKeySoundSystem
       
    25 
       
    26 #include <cameraapp.rsg>
       
    27 #include <vgacamsettings.rsg>
       
    28 
       
    29 #include "camlogging.h"
       
    30 
       
    31 #include "CamSettingsInternal.hrh"       // TCamCameraMode, TCamSettingItemIds
       
    32 #include "CamAppController.h"
       
    33 #include "mcamplayerobserver.h"
       
    34 #include "mcamplayerwrapper.h"
       
    35 #include "camaudioplayerwrapper.h"
       
    36 #include "camtoneplayerwrapper.h"
       
    37 #include "camaudioplayercontroller.h"
       
    38 #include "OstTraceDefinitions.h"
       
    39 #ifdef OST_TRACE_COMPILER_IN_USE
       
    40 #include "camaudioplayercontrollerTraces.h"
       
    41 #endif
       
    42 
       
    43 
       
    44 
       
    45 // ===========================================================================
       
    46 // Constants
       
    47 namespace NCamAudioPlayerController
       
    48   {
       
    49   static const TInt KImageCaptureSoundId = KMinTInt;
       
    50 
       
    51 
       
    52   // Cached sounds which are loaded once entering image mode.
       
    53   // No need to include capture sound, it is selected based
       
    54   // on the setting.
       
    55   static const TInt KImageCachedSounds[] =
       
    56     {
       
    57     // Our own id for image capture sound,
       
    58     // which can change.
       
    59     // Also avoid compilation error, if AF beep not supported.
       
    60     KImageCaptureSoundId,
       
    61     ECamAutoFocusComplete
       
    62     };
       
    63   
       
    64   // Cached sounds which are loaded once entering video mode.
       
    65   static const TInt KVideoCachedSounds[] =
       
    66     {
       
    67     ECamVideoStartSoundId,
       
    68     ECamVideoStopSoundId,
       
    69     ECamVideoPauseSoundId,
       
    70     ECamVideoResumeSoundId
       
    71     };
       
    72   }
       
    73 
       
    74 using namespace NCamAudioPlayerController;
       
    75 
       
    76 // ===========================================================================
       
    77 // public constructors and destructor
       
    78 
       
    79 // ---------------------------------------------------------------------------
       
    80 // NewL <<static>>
       
    81 // ---------------------------------------------------------------------------
       
    82 //
       
    83 CCamAudioPlayerController* 
       
    84 CCamAudioPlayerController::NewL( CCamAppController&  aController,
       
    85                                  MCamPlayerObserver& aObserver )
       
    86   {
       
    87   CCamAudioPlayerController* self = 
       
    88     new (ELeave) CCamAudioPlayerController( aController, aObserver );
       
    89     
       
    90   CleanupStack::PushL( self );
       
    91   self->ConstructL();
       
    92   CleanupStack::Pop( self );
       
    93 
       
    94   return self;  
       
    95   }
       
    96 
       
    97 // ---------------------------------------------------------------------------
       
    98 // destructor <<virtual>>
       
    99 // ---------------------------------------------------------------------------
       
   100 //
       
   101 CCamAudioPlayerController::~CCamAudioPlayerController()
       
   102   {
       
   103   iController.RemoveControllerObserver( this );
       
   104   iController.RemoveSettingsObserver( this );
       
   105 
       
   106   Reset();
       
   107   iPlayers.Close();
       
   108 
       
   109   iKeySoundSystem = NULL; // not own
       
   110   }
       
   111 
       
   112 
       
   113 
       
   114 
       
   115 // ===========================================================================
       
   116 // From MCamControllerObserver
       
   117 
       
   118 // ---------------------------------------------------------------------------
       
   119 // HandleControllerEventL <<virtual>>
       
   120 // ---------------------------------------------------------------------------
       
   121 //
       
   122 void 
       
   123 CCamAudioPlayerController
       
   124 ::HandleControllerEventL( TCamControllerEvent aEvent,
       
   125                           TInt                aError )
       
   126   {
       
   127   PRINT( _L("Camera => CCamAudioPlayerController::HandleControllerEventL") );
       
   128   switch( aEvent )
       
   129     {
       
   130     case ECamEventEngineStateChanged:
       
   131       {
       
   132       PRINT( _L("Camera <> CCamAudioPlayerController: case ECamEventEngineStateChanged") );
       
   133       if( KErrNone == aError )
       
   134         {
       
   135         TCamCameraMode mode = iController.CurrentMode();
       
   136         PRINT2( _L("Camera <> CCamAudioPlayerController: KErrNone, old mode[%s] new mode[%s]"), KCamModeNames[iCameraMode], KCamModeNames[mode] );
       
   137         if( mode != iCameraMode )
       
   138           {
       
   139           // Changing to video or image mode.
       
   140           // Cache the players needed.
       
   141           // If this fails we just retry once a sound is really needed.
       
   142           if     ( ECamControllerImage    == mode 
       
   143                 || ECamControllerVideo    == mode ) { Setup( mode ); }
       
   144           // Changing to shutdown mode
       
   145           // Release all players.
       
   146           else if( ECamControllerShutdown == mode || ECamControllerIdle == mode ) 
       
   147         	  {
       
   148         	  Setup( mode );
       
   149         	  }
       
   150           // Other mode entered, no action
       
   151           else                                      { /* no action */ }
       
   152           }
       
   153         }
       
   154       else
       
   155         {
       
   156         PRINT1( _L("Camera <> CCamAudioPlayerController: error in (%d), call Reset.."), aError );
       
   157         Reset();
       
   158         }
       
   159       break;
       
   160       }
       
   161 
       
   162     default:
       
   163       {
       
   164       break;
       
   165       }
       
   166     }
       
   167   PRINT( _L("Camera <= CCamAudioPlayerController::HandleControllerEventL") );
       
   168   }
       
   169 
       
   170 
       
   171 
       
   172 // ===========================================================================
       
   173 // From MCamSettingsModelObserver
       
   174 
       
   175 // ---------------------------------------------------------------------------
       
   176 // IntSettingChangedL <<virtual>>
       
   177 // ---------------------------------------------------------------------------
       
   178 //
       
   179 void 
       
   180 CCamAudioPlayerController
       
   181 ::IntSettingChangedL( TCamSettingItemIds aSettingItem, 
       
   182                       TInt               /*aSettingValue*/ )
       
   183   {
       
   184   PRINT( _L("Camera => CCamAudioPlayerController::IntSettingChangedL") );
       
   185   switch( aSettingItem )
       
   186     {
       
   187     case ECamSettingItemPhotoCaptureTone:
       
   188       {
       
   189       PRINT( _L("Camera <> CCamAudioPlayerController: case ECamSettingItemPhotoCaptureTone") );
       
   190 
       
   191       // The setting value is *not* of TCamSoundId type.
       
   192       // See CCamAppController::CaptureToneId().
       
   193       const TCamSoundId newSoundId = iController.CaptureToneId();
       
   194       SetupCaptureSoundPlayerL( newSoundId );
       
   195 
       
   196       break;
       
   197       }
       
   198     default:
       
   199       {
       
   200       break;
       
   201       }
       
   202     }
       
   203 
       
   204   PRINT( _L("Camera <= CCamAudioPlayerController::IntSettingChangedL") );
       
   205   }
       
   206 
       
   207 
       
   208 // ---------------------------------------------------------------------------
       
   209 // TextSettingChangedL <<virtual>>
       
   210 // ---------------------------------------------------------------------------
       
   211 //
       
   212 void 
       
   213 CCamAudioPlayerController
       
   214 ::TextSettingChangedL(       TCamSettingItemIds /*aSettingItem*/, 
       
   215                        const TDesC&             /*aSettingValue*/ )
       
   216   {
       
   217   // these events are ignored
       
   218   }
       
   219 
       
   220 
       
   221 
       
   222 // ===========================================================================
       
   223 // new public
       
   224 
       
   225 // ---------------------------------------------------------------------------
       
   226 // PlaySound
       
   227 // ---------------------------------------------------------------------------
       
   228 //
       
   229 void 
       
   230 CCamAudioPlayerController::PlaySound( TInt  aSoundId,
       
   231                                       TBool aCallback )
       
   232   {
       
   233   TRAPD( status,
       
   234     {
       
   235     // Get cached player, if available.
       
   236     // Otherwise create new one.
       
   237     CCamPlayerWrapperBase* player = GetPlayerL( aSoundId );
       
   238     player->Play( aCallback );
       
   239     });
       
   240 
       
   241   if( KErrNone != status )
       
   242     {
       
   243     if( KErrNoMemory == status )
       
   244       {
       
   245       // If OOM, release all players.
       
   246       // Create new ones again when needed.
       
   247       Reset();
       
   248       }
       
   249     if( aCallback )
       
   250       {
       
   251       // If could not instantiate a player, notify observer right away.
       
   252       iObserver.PlayComplete( status, aSoundId );
       
   253       }
       
   254     }
       
   255   }
       
   256 
       
   257 
       
   258 // ---------------------------------------------------------------------------
       
   259 // PlayTone
       
   260 // ---------------------------------------------------------------------------
       
   261 // 
       
   262 void
       
   263 CCamAudioPlayerController::PlayTone( TInt    aToneInHz, 
       
   264                                      TInt    aLengthInUs, 
       
   265                                      TReal32 aVolumeInPercent, 
       
   266                                      TBool   aCallback )
       
   267   {
       
   268   TInt status( KErrNone );
       
   269 
       
   270   if( !iTonePlayer )
       
   271     {
       
   272     TRAP( status, iTonePlayer = CCamTonePlayerWrapper::NewL( iObserver ) );
       
   273     }
       
   274 
       
   275   if( KErrNone == status )
       
   276     {
       
   277     iTonePlayer->PlayTone( aToneInHz, aLengthInUs, aVolumeInPercent, aCallback );
       
   278     }
       
   279   else
       
   280     {
       
   281     if( aCallback )
       
   282       iObserver.PlayComplete( status, -1 );
       
   283     }
       
   284   }
       
   285   
       
   286 
       
   287 // ---------------------------------------------------------------------------
       
   288 // CancelAllPlaying
       
   289 // ---------------------------------------------------------------------------
       
   290 //
       
   291 void 
       
   292 CCamAudioPlayerController::CancelAllPlaying()
       
   293   {
       
   294   PRINT( _L("Camera => CCamAudioPlayerController::CancelAllPlaying") );
       
   295 
       
   296   if( iTonePlayer )
       
   297     {
       
   298     iTonePlayer->CancelPlay();
       
   299     }
       
   300   for( TInt i = 0; i < iPlayers.Count(); i++ )
       
   301     {
       
   302     iPlayers[i]->CancelPlay();
       
   303     }
       
   304 
       
   305   PRINT( _L("Camera <= CCamAudioPlayerController::CancelAllPlaying") );
       
   306   }
       
   307 
       
   308 // ---------------------------------------------------------------------------
       
   309 // CancelPlaying
       
   310 // ---------------------------------------------------------------------------
       
   311 //
       
   312 void 
       
   313 CCamAudioPlayerController::CancelPlaying( TInt aSoundId )
       
   314   {
       
   315   TInt index = FindPlayerIndex( aSoundId );
       
   316   if( KErrNotFound != index )
       
   317     {
       
   318     CCamPlayerWrapperBase* player = iPlayers[index];
       
   319     player->CancelPlay();
       
   320     }
       
   321   }
       
   322 
       
   323 
       
   324 // ---------------------------------------------------------------------------
       
   325 // InitKeySoundSystem
       
   326 // ---------------------------------------------------------------------------
       
   327 // 
       
   328 void
       
   329 CCamAudioPlayerController::InitKeySoundSystem()
       
   330   {
       
   331   PRINT( _L("Camera => CCamAudioPlayerController::InitKeySoundSystem") );
       
   332   iKeySoundSystem = static_cast<CAknAppUi*>( CEikonEnv::Static()->AppUi() )->KeySounds();
       
   333   /* No sounds played via iKeySoundSystem. No need to add sound list.
       
   334   if( !iKeySoundSystem )
       
   335     {
       
   336     iKeySoundSystem = static_cast<CAknAppUi*>( CEikonEnv::Static()->AppUi() )->KeySounds();
       
   337     if ( iKeySoundSystem )
       
   338       {
       
   339       TRAPD( status, iKeySoundSystem->AddAppSoundInfoListL( R_CAM_SOUND_LIST ) );
       
   340       PRINT1( _L("Camera <> CCamAudioPlayerController: status:%d"), status );
       
   341       if( KErrNone          != status
       
   342        && KErrAlreadyExists != status
       
   343         )
       
   344         {
       
   345         // Set unusable
       
   346         iKeySoundSystem = NULL;
       
   347         }  
       
   348       }
       
   349     }
       
   350   */
       
   351   PRINT( _L("Camera <= CCamAudioPlayerController::InitKeySoundSystem") );
       
   352   }
       
   353 
       
   354 // ---------------------------------------------------------------------------
       
   355 // EnableAllKeySounds
       
   356 // ---------------------------------------------------------------------------
       
   357 //
       
   358 void 
       
   359 CCamAudioPlayerController::EnableAllKeySounds()
       
   360   {
       
   361   if ( iKeySoundSystem && iKeySoundsDisabled )
       
   362     {
       
   363     iKeySoundSystem->ReleaseContext();
       
   364     iKeySoundSystem->PopContext();
       
   365     iKeySoundsDisabled = EFalse;
       
   366     }
       
   367   }
       
   368 
       
   369 
       
   370 // ---------------------------------------------------------------------------
       
   371 // DisableAllKeySoundsL
       
   372 // ---------------------------------------------------------------------------
       
   373 //
       
   374 void 
       
   375 CCamAudioPlayerController::DisableAllKeySoundsL()
       
   376   {
       
   377   if ( iKeySoundSystem && !iKeySoundsDisabled )    
       
   378     {
       
   379     iKeySoundSystem->PushContextL( R_AVKON_SILENT_SKEY_LIST );
       
   380     iKeySoundSystem->BringToForeground();
       
   381     iKeySoundSystem->LockContext();
       
   382     iKeySoundsDisabled = ETrue;
       
   383     }
       
   384   }
       
   385 
       
   386 
       
   387 
       
   388 
       
   389 // ===========================================================================
       
   390 // new private
       
   391 
       
   392 // ---------------------------------------------------------------------------
       
   393 // FindPlayerIndex
       
   394 // ---------------------------------------------------------------------------
       
   395 //
       
   396 TInt 
       
   397 CCamAudioPlayerController::FindPlayerIndex( TInt aSoundId ) const
       
   398   {
       
   399   TInt found = KErrNotFound;
       
   400 
       
   401   // Check that id is valid.
       
   402   if( aSoundId > 0 )
       
   403     {
       
   404     TInt current = iPlayers.Count(); 
       
   405     while( --current >= 0 )
       
   406       {
       
   407       // Reuse player, if the sound is the same despite
       
   408       // sound id being different.
       
   409       // if( aSoundId == iPlayers[current]->Id() )
       
   410       if( iPlayers[current]->IsEqualSound( aSoundId ) )
       
   411         {
       
   412         found   = current;
       
   413         current = -1;
       
   414         }
       
   415       }
       
   416     }
       
   417   return found;
       
   418   }
       
   419     
       
   420 // ---------------------------------------------------------------------------
       
   421 // GetPlayerL
       
   422 // ---------------------------------------------------------------------------
       
   423 //
       
   424 CCamPlayerWrapperBase*
       
   425 CCamAudioPlayerController::GetPlayerL( TInt aSoundId )
       
   426   {
       
   427   PRINT1( _L("Camera => CCamAudioPlayerController::GetPlayerL, sound id:%d"), aSoundId );
       
   428   CCamPlayerWrapperBase* player( NULL );
       
   429   
       
   430   if( KImageCaptureSoundId == aSoundId )
       
   431     {
       
   432     player = GetPlayerL( iController.CaptureToneId() );
       
   433     }
       
   434   else
       
   435     {
       
   436     TInt index = FindPlayerIndex( aSoundId );
       
   437   
       
   438     if( KErrNotFound != index )
       
   439       {
       
   440       player = iPlayers[index];
       
   441       }
       
   442     else
       
   443       {
       
   444       OstTrace0( CAMERAAPP_PERFORMANCE, CCAMAUDIOPLAYERCONTROLLER_GETPLAYERL, "e_CAM_APP_CAPTURE_SOUND_LOAD 1" ); //CCORAPP_CAPTURE_SOUND_LOAD_START
       
   445       
       
   446       player = CCamAudioPlayerWrapper::NewL( iObserver, aSoundId );
       
   447   
       
   448       CleanupStack::PushL( player );
       
   449       iPlayers.AppendL( player );
       
   450       CleanupStack::Pop( player );
       
   451       OstTrace0( CAMERAAPP_PERFORMANCE, DUP1_CCAMAUDIOPLAYERCONTROLLER_GETPLAYERL, "e_CAM_APP_CAPTURE_SOUND_LOAD 0" ); //CCORAPP_CAPTURE_SOUND_LOAD_END
       
   452       }
       
   453     }
       
   454 
       
   455   PRINT( _L("Camera <= CCamAudioPlayerController::GetPlayerL") );
       
   456   return player;
       
   457   }
       
   458 
       
   459 
       
   460 
       
   461 // ---------------------------------------------------------------------------
       
   462 // RemovePlayer
       
   463 // ---------------------------------------------------------------------------
       
   464 //
       
   465 void
       
   466 CCamAudioPlayerController::RemovePlayer( TInt aSoundId )
       
   467   {
       
   468   TInt index = FindPlayerIndex( aSoundId );
       
   469   if( KErrNotFound != index )
       
   470     {
       
   471     CCamPlayerWrapperBase* player = iPlayers[index];
       
   472     iPlayers.Remove( index );
       
   473     delete player;
       
   474     player = NULL;
       
   475     }
       
   476   }
       
   477 
       
   478 // ---------------------------------------------------------------------------
       
   479 // Setup
       
   480 // ---------------------------------------------------------------------------
       
   481 //
       
   482 void 
       
   483 CCamAudioPlayerController::Setup( TCamCameraMode aCameraMode )
       
   484   {
       
   485   PRINT( _L("Camera => CCamAudioPlayerController::Setup") );
       
   486   Reset();
       
   487 
       
   488   TInt status( KErrNone );  
       
   489   switch( aCameraMode )
       
   490     {
       
   491     case ECamControllerImage:
       
   492       {
       
   493       TRAP( status, SetupForImageL() );
       
   494       break;
       
   495       }
       
   496 
       
   497     case ECamControllerVideo:
       
   498       {
       
   499       TRAP( status, SetupForVideoL() );
       
   500       break;
       
   501       }
       
   502 
       
   503     case ECamControllerIdle:
       
   504     case ECamControllerShutdown:
       
   505     default:
       
   506       {
       
   507       // Already reset, no sounds needed now.
       
   508       break;
       
   509       }
       
   510     }
       
   511 
       
   512   // If any problems, try reload sounds once really needed, so reset now.
       
   513   if( KErrNone != status ) 
       
   514     Reset();
       
   515   else
       
   516     iCameraMode = aCameraMode;
       
   517 
       
   518   PRINT( _L("Camera <= CCamAudioPlayerController::Setup") );
       
   519   }
       
   520 
       
   521 // ---------------------------------------------------------------------------
       
   522 // SetupForVideoL
       
   523 // ---------------------------------------------------------------------------
       
   524 //
       
   525 void
       
   526 CCamAudioPlayerController::SetupForVideoL()
       
   527   {
       
   528   PRINT( _L("Camera => CCamAudioPlayerController::SetupForVideoL") );
       
   529   InitKeySoundSystem();
       
   530 
       
   531   TInt count( sizeof( KVideoCachedSounds ) / sizeof( TInt ) );
       
   532   PRINT1( _L("Camera <> CCamAudioPlayerController: count of players to load: %d"), count );
       
   533   for( TInt i = 0; i < count; i++ )
       
   534     {
       
   535     GetPlayerL( KVideoCachedSounds[i] );
       
   536     }
       
   537   PRINT( _L("Camera <= CCamAudioPlayerController::SetupForVideoL") );
       
   538   }
       
   539 
       
   540 // ---------------------------------------------------------------------------
       
   541 // SetupForImageL
       
   542 // ---------------------------------------------------------------------------
       
   543 //
       
   544 void 
       
   545 CCamAudioPlayerController::SetupForImageL()
       
   546   {
       
   547   PRINT( _L("Camera => CCamAudioPlayerController::SetupForImageL") );
       
   548   TInt count( sizeof( KImageCachedSounds ) / sizeof( TInt ) );
       
   549 
       
   550   PRINT1( _L("Camera <> CCamAudioPlayerController: count of players to load: %d"), count );
       
   551   for( TInt i = 0; i < count; i++ )
       
   552     {
       
   553     GetPlayerL( KImageCachedSounds[i] );
       
   554     }
       
   555   PRINT( _L("Camera => CCamAudioPlayerController::SetupForImageL") );
       
   556   }
       
   557 
       
   558 // ---------------------------------------------------------------------------
       
   559 // SetupCaptureSoundPlayerL
       
   560 // ---------------------------------------------------------------------------
       
   561 //
       
   562 void
       
   563 CCamAudioPlayerController::SetupCaptureSoundPlayerL( TInt aNewSoundId )
       
   564   {
       
   565   PRINT2( _L("Camera => CCamAudioPlayerController::SetupCaptureSoundPlayerL, old sound:%d new sound:%d"), iCaptureSoundId, aNewSoundId );
       
   566 
       
   567   if( aNewSoundId != iCaptureSoundId )
       
   568     {
       
   569     // Free old player, if exists.
       
   570     RemovePlayer( iCaptureSoundId );
       
   571   
       
   572     // If loading new fails, retry when sound is needed.
       
   573     iCaptureSoundId = -1;
       
   574     GetPlayerL( aNewSoundId ); 
       
   575     iCaptureSoundId = aNewSoundId;
       
   576     }
       
   577   PRINT ( _L("Camera <= CCamAudioPlayerController::SetupCaptureSoundPlayerL") );
       
   578   }
       
   579 
       
   580 // ---------------------------------------------------------------------------
       
   581 // Reset
       
   582 // ---------------------------------------------------------------------------
       
   583 //
       
   584 void 
       
   585 CCamAudioPlayerController::Reset()
       
   586   {
       
   587   PRINT ( _L("Camera => CCamAudioPlayerController::Reset") );
       
   588   iPlayers.ResetAndDestroy();
       
   589 
       
   590   delete iTonePlayer;
       
   591   iTonePlayer = NULL;
       
   592 
       
   593   iCameraMode     = ECamControllerIdle;
       
   594   iCaptureSoundId = -1;
       
   595   PRINT ( _L("Camera <= CCamAudioPlayerController::Reset") );
       
   596   }
       
   597 
       
   598 
       
   599 
       
   600 // ===========================================================================
       
   601 // private constructors
       
   602 
       
   603 // ---------------------------------------------------------------------------
       
   604 // ConstructL
       
   605 // ---------------------------------------------------------------------------
       
   606 //
       
   607 void 
       
   608 CCamAudioPlayerController::ConstructL()
       
   609   {
       
   610   iController.AddControllerObserverL( this );
       
   611   iController.AddSettingsObserverL( this );
       
   612   }
       
   613 
       
   614 // ---------------------------------------------------------------------------
       
   615 // constructor
       
   616 // ---------------------------------------------------------------------------
       
   617 //
       
   618 CCamAudioPlayerController
       
   619 ::CCamAudioPlayerController( CCamAppController&  aController,
       
   620                              MCamPlayerObserver& aObserver )
       
   621   : iController       ( aController            ),
       
   622     iObserver         ( aObserver              ),
       
   623     iCameraMode       ( ECamControllerIdle ),
       
   624     iCaptureSoundId   ( -1                     ),
       
   625     iKeySoundsDisabled( EFalse                 )
       
   626   {
       
   627   }
       
   628 
       
   629 // ===========================================================================  
       
   630 // end of file
       
   631