mpxplugins/viewplugins/views/podcastplaybackview/src/mpxpodcastplaybackviewimp.cpp
branchRCL_3
changeset 26 3de6c4cf6b67
equal deleted inserted replaced
25:14979e23cb5e 26:3de6c4cf6b67
       
     1 /*
       
     2 * Copyright (c) 2006 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 Podcast playback view
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 // INCLUDE FILES
       
    21 #include <StringLoader.h>
       
    22 #include <aknViewAppUi.h>
       
    23 #include <eikmenub.h>
       
    24 #include <eikapp.h>
       
    25 #include <AknUtils.h>
       
    26 #include <bautils.h>
       
    27 #include <data_caging_path_literals.hrh>
       
    28 #include <mpxpodcastplaybackview.rsg>
       
    29 #include <mpxcommonplaybackview.rsg>
       
    30 #include <featmgr.h>
       
    31 
       
    32 #include <mpxcollectionframeworkdefs.h>
       
    33 #include <mpxcollectionmessage.h>
       
    34 #include <mpxcollectionutility.h>
       
    35 #include <mpxcollectionhelperfactory.h>
       
    36 #include <mpxcollectionuihelper.h>
       
    37 #include <mpxcollectionpath.h>
       
    38 #include <mpxcollectionplaylist.h>
       
    39 #include <mpxmedia.h>
       
    40 #include <mpxviewutility.h>
       
    41 #include <mpxviewpluginmanager.h>
       
    42 #include <mpxmediamusicdefs.h>
       
    43 #include <mpxpodcastdefs.h>
       
    44 #include <mpxmediadrmdefs.h>
       
    45 #include <mpxplaybackutility.h>
       
    46 #include <mpxmessagegeneraldefs.h>
       
    47 #include <mpxplaybackmessage.h>
       
    48 #include <mpxuser.h>
       
    49 #include <mpxappui.hrh>
       
    50 #include "mpxcommonplaybackview.hrh"
       
    51 #include "mpxpodcastplaybackviewimp.h"
       
    52 #include "mpxpodcastplaybackviewcontainer.h"
       
    53 #include "mpxpodcastplaybackviewlayout.h"
       
    54 #include "mpxpodcastplaybackview.hrh"
       
    55 #include "mpxlog.h"
       
    56 
       
    57 #include "mpxcommonplaybackview.hrh"
       
    58 
       
    59 #include <akntoolbar.h>
       
    60 #include <aknbutton.h>
       
    61 // CONSTANTS
       
    62 _LIT( KMPXPodcastPlaybackRscPath, "mpxpodcastplaybackview.rsc" );
       
    63 const TInt KPodcastingCollectionID = 0x101FFC3C;
       
    64 
       
    65 // ======== MEMBER FUNCTIONS ========
       
    66 
       
    67 // ---------------------------------------------------------------------------
       
    68 // C++ default constructor can NOT contain any code, that
       
    69 // might leave.
       
    70 // ---------------------------------------------------------------------------
       
    71 //
       
    72 CMPXPodcastPlaybackViewImp::CMPXPodcastPlaybackViewImp()
       
    73     {
       
    74     }
       
    75 
       
    76 // ---------------------------------------------------------------------------
       
    77 // Symbian 2nd phase constructor can leave.
       
    78 // ---------------------------------------------------------------------------
       
    79 //
       
    80 void CMPXPodcastPlaybackViewImp::ConstructL()
       
    81     {
       
    82     MPX_FUNC( "CMPXPodcastPlaybackViewImp::ConstructL" );
       
    83 
       
    84     CCoeEnv* coeEnv = iEikonEnv;
       
    85     TParse parse;
       
    86     parse.Set( KMPXPodcastPlaybackRscPath, &KDC_APP_RESOURCE_DIR, NULL );
       
    87     TFileName resourceFile( parse.FullName() );
       
    88     User::LeaveIfError( MPXUser::CompleteWithDllPath( resourceFile ) );
       
    89     BaflUtils::NearestLanguageFile( coeEnv->FsSession(), resourceFile );
       
    90     iPodcastResourceOffset = coeEnv->AddResourceFileL( resourceFile );
       
    91 
       
    92     CMPXCommonPlaybackViewImp::ConstructL();
       
    93 
       
    94     BaseConstructL( R_MPX_PODCAST_PLAYBACK_VIEW );
       
    95     if(AknLayoutUtils::PenEnabled())
       
    96     {
       
    97     if ( Toolbar() )
       
    98         {
       
    99         iToolbar = Toolbar();
       
   100         iToolbar->SetToolbarObserver( this );
       
   101         }
       
   102     }
       
   103 
       
   104     }
       
   105 
       
   106 // ---------------------------------------------------------------------------
       
   107 // Two-phased constructor.
       
   108 // ---------------------------------------------------------------------------
       
   109 //
       
   110 CMPXPodcastPlaybackViewImp* CMPXPodcastPlaybackViewImp::NewL()
       
   111     {
       
   112     CMPXPodcastPlaybackViewImp* self = CMPXPodcastPlaybackViewImp::NewLC();
       
   113     CleanupStack::Pop( self );
       
   114     return self;
       
   115     }
       
   116 
       
   117 // ---------------------------------------------------------------------------
       
   118 // Two-phased constructor.
       
   119 // ---------------------------------------------------------------------------
       
   120 //
       
   121 CMPXPodcastPlaybackViewImp* CMPXPodcastPlaybackViewImp::NewLC()
       
   122     {
       
   123     CMPXPodcastPlaybackViewImp* self = new ( ELeave ) CMPXPodcastPlaybackViewImp();
       
   124     CleanupStack::PushL( self );
       
   125     self->ConstructL();
       
   126     return self;
       
   127     }
       
   128 
       
   129 // ---------------------------------------------------------------------------
       
   130 // Destructor
       
   131 // ---------------------------------------------------------------------------
       
   132 //
       
   133 CMPXPodcastPlaybackViewImp::~CMPXPodcastPlaybackViewImp()
       
   134     {
       
   135     MPX_DEBUG1( "CMPXPodcastPlaybackViewImp::~CMPXPodcastPlaybackViewImp entering" );
       
   136 
       
   137     delete iPlaybackViewLayout;
       
   138 
       
   139     if ( iPodcastResourceOffset )
       
   140         {
       
   141         iEikonEnv->DeleteResourceFile( iPodcastResourceOffset );
       
   142         }
       
   143 
       
   144     MPX_DEBUG1( "CMPXPodcastPlaybackViewImp::~CMPXPodcastPlaybackViewImp exiting" );
       
   145     }
       
   146 
       
   147 // ---------------------------------------------------------------------------
       
   148 // From base class CMPXCommonPlaybackViewImp
       
   149 //
       
   150 // Handle playback property.
       
   151 // ---------------------------------------------------------------------------
       
   152 //
       
   153 void CMPXPodcastPlaybackViewImp::DoHandlePropertyL(
       
   154     TMPXPlaybackProperty aProperty,
       
   155     TInt aValue,
       
   156     TInt aError )
       
   157     {
       
   158     MPX_FUNC( "CMPXPodcastPlaybackViewImp::DoHandlePropertyL" );
       
   159     MPX_DEBUG4( "HandlePropertyL - Property(%d); Value(%d); Error(%d)", aProperty, aValue, aError );
       
   160 
       
   161     if ( KErrNone == aError )
       
   162         {
       
   163         switch ( aProperty  )
       
   164             {
       
   165             case EPbPropertyPosition:
       
   166                 {
       
   167                 if (iPosition == 0 && aValue != 0)
       
   168                     {
       
   169                     MMPXSource* s = iPlaybackUtility->Source();
       
   170                     if (s)
       
   171                         {
       
   172                         // Trick to make the song played
       
   173                         CMPXCollectionPlaylist* playlist = s->PlaylistL();
       
   174                         CleanupStack::PushL(playlist);
       
   175                         if ( playlist )
       
   176                             {
       
   177                             CMPXMedia* media = CMPXMedia::NewL();
       
   178                             CleanupStack::PushL(media);
       
   179                             media->SetTObjectValueL( KMPXMediaGeneralType,
       
   180                                                      EMPXItem );
       
   181                             media->SetTObjectValueL( KMPXMediaGeneralCategory,
       
   182                                                      EMPXSong );
       
   183                             media->SetTObjectValueL( KMPXMediaGeneralCollectionId,
       
   184                                                      playlist->Path().Id( CMPXCollectionPath::ECollectionUid ).iId1);
       
   185 
       
   186                             media->SetTObjectValueL<TMPXItemId>( KMPXMediaGeneralId , playlist->Path().Id() );
       
   187                             media->SetTObjectValueL( KMPXMediaGeneralLastPlaybackPosition, aValue );
       
   188                             playlist->SetL( *media );
       
   189                             CleanupStack::PopAndDestroy(media);
       
   190                             }
       
   191                         CleanupStack::PopAndDestroy(playlist);
       
   192                         }
       
   193                     }
       
   194                 iPosition = aValue;
       
   195                 CMPXCommonPlaybackViewImp::DoHandlePropertyL(aProperty, aValue, aError);
       
   196                 break;
       
   197                 }
       
   198             default:
       
   199                 {
       
   200                 CMPXCommonPlaybackViewImp::DoHandlePropertyL(aProperty,
       
   201                     aValue,
       
   202                     aError);
       
   203                 break;
       
   204                 }
       
   205             }
       
   206         }
       
   207     else
       
   208         {
       
   209         HandleErrorL( aError );
       
   210         }
       
   211     }
       
   212 
       
   213 // ---------------------------------------------------------------------------
       
   214 // Updates track info field.
       
   215 // ---------------------------------------------------------------------------
       
   216 //
       
   217 void CMPXPodcastPlaybackViewImp::UpdateTrackInfoL(
       
   218     const CMPXMedia* aMedia )
       
   219     {
       
   220     MPX_FUNC( "CMPXPodcastPlaybackViewImp::UpdateTrackInfo" );
       
   221 
       
   222     CMPXCommonPlaybackViewImp::UpdateTrackInfoL( aMedia );
       
   223 
       
   224     if( iContainer && !iSwitchingView )
       
   225         {
       
   226         if ( aMedia )
       
   227             {
       
   228             // Set ETextArtist field as Podcast Title
       
   229             if ( aMedia->IsSupported(KMPXMediaMusicAlbum))
       
   230                 {
       
   231                 HBufC* titleText = aMedia->ValueText(KMPXMediaMusicAlbum).AllocL();
       
   232                 CleanupStack::PushL(titleText);
       
   233                 if ( titleText->Length() > 0)
       
   234                     {
       
   235                     iContainer->UpdateLabelL( ETextArtist, *titleText );
       
   236                     }
       
   237                 else
       
   238                     {
       
   239                     HBufC* unknownText =
       
   240                         StringLoader::LoadLC( R_MPX_QTN_NMP_UNKNOWN_TITLE );
       
   241                     iContainer->UpdateLabelL(
       
   242                         ETextArtist, *unknownText );
       
   243                     CleanupStack::PopAndDestroy( unknownText );
       
   244                     }
       
   245                 CleanupStack::PopAndDestroy( titleText );
       
   246                 }
       
   247             else
       
   248                 {
       
   249                 HBufC* unknownText =
       
   250                         StringLoader::LoadLC( R_MPX_QTN_NMP_UNKNOWN_TITLE );
       
   251                 iContainer->UpdateLabelL(
       
   252                     ETextArtist, *unknownText );
       
   253                 CleanupStack::PopAndDestroy( unknownText );
       
   254                 }
       
   255             }
       
   256         }
       
   257     }
       
   258 
       
   259 // ---------------------------------------------------------------------------
       
   260 // From MEikMenuObserver
       
   261 // Dynamically initialises a menu pane.
       
   262 // ---------------------------------------------------------------------------
       
   263 //
       
   264 void CMPXPodcastPlaybackViewImp::DynInitMenuPaneL(
       
   265     TInt aResourceId,
       
   266     CEikMenuPane* aMenuPane )
       
   267     {
       
   268     switch( aResourceId )
       
   269         {
       
   270         case R_MPX_PODCAST_PLAYBACK_VIEW_MENU1:
       
   271             {
       
   272             break;
       
   273             }
       
   274         case R_MPX_PLAYBACK_VIEW_MENU:
       
   275             {
       
   276             CMPXCommonPlaybackViewImp::DynInitMenuPaneL( aResourceId, aMenuPane );
       
   277 
       
   278             // dim the options that aren't applicable
       
   279             // to podcast collection
       
   280             aMenuPane->SetItemDimmed(
       
   281                     EMPXPbvCmdGotoMusicMenu,
       
   282                     ETrue );
       
   283             aMenuPane->SetItemDimmed(
       
   284                     EMPXPbvCmdAddToPlaylist,
       
   285                     ETrue );
       
   286             aMenuPane->SetItemDimmed(
       
   287                 EMPXPbvCmdUseAsCascade,
       
   288                 ETrue );
       
   289             aMenuPane->SetItemDimmed(
       
   290                     EMPXPbvCmdRepeat,
       
   291                     ETrue );
       
   292             aMenuPane->SetItemDimmed(
       
   293                     EMPXPbvCmdRandom,
       
   294                     ETrue );
       
   295             aMenuPane->SetItemDimmed(
       
   296                     EMPXPbvCmdSongDetails,
       
   297                     ETrue );
       
   298 
       
   299 			// Check if FM Transmitter is supported
       
   300 			if ( !FeatureManager::FeatureSupported( KFeatureIdFmtx ) )
       
   301 				{
       
   302 				aMenuPane->SetItemDimmed(
       
   303 					EMPXPbvCmdFMTransmitter,
       
   304 					ETrue );
       
   305 				}
       
   306             break;
       
   307             }
       
   308         default:
       
   309             {
       
   310             // Call base clase to handle most cases
       
   311             CMPXCommonPlaybackViewImp::DynInitMenuPaneL(
       
   312                 aResourceId,
       
   313                 aMenuPane );
       
   314             break;
       
   315             }
       
   316         }
       
   317     }
       
   318 
       
   319 // ---------------------------------------------------------------------------
       
   320 // From CAknView
       
   321 // Returns views id.
       
   322 // ---------------------------------------------------------------------------
       
   323 //
       
   324 TUid CMPXPodcastPlaybackViewImp::Id() const
       
   325     {
       
   326     return TUid::Uid( KMPXPodcastPlaybackViewId );
       
   327     }
       
   328 
       
   329 // ---------------------------------------------------------------------------
       
   330 // From CAknView
       
   331 // Command handling function.
       
   332 // ---------------------------------------------------------------------------
       
   333 //
       
   334 EXPORT_C void CMPXPodcastPlaybackViewImp::HandleCommandL( TInt aCommand )
       
   335     {
       
   336     switch( aCommand )
       
   337         {
       
   338         case EMPXPbvCmdGoToPodcastMenu:
       
   339             {
       
   340             // Handle Goto main podcast menu
       
   341             CMPXCollectionPath* cpath = iCollectionUiHelper->PodCastMenuPathL();
       
   342             CleanupStack::PushL( cpath );
       
   343             MPX_DEBUG_PATH (*cpath);
       
   344             iCollectionUtility->Collection().OpenL( *cpath );
       
   345             CleanupStack::PopAndDestroy( cpath );
       
   346 
       
   347             // Restore status pane
       
   348             if ( StatusPane()->CurrentLayoutResId() !=
       
   349                  R_AVKON_STATUS_PANE_LAYOUT_USUAL)
       
   350                 {
       
   351                 StatusPane()->SwitchLayoutL(R_AVKON_STATUS_PANE_LAYOUT_USUAL);
       
   352                 }
       
   353             break;
       
   354             }
       
   355         case EAknSoftkeyBack:
       
   356             {
       
   357             MMPXSource* s = iPlaybackUtility->Source();
       
   358             TBool handled = EFalse;
       
   359             if(s == NULL)
       
   360                 {
       
   361                 CMPXCollectionPath* path = iCollectionUtility->Collection().PathL();
       
   362                 CleanupStack::PushL(path);
       
   363                 TInt levels = path->Levels();
       
   364                 if(levels == 3)
       
   365                     {
       
   366                     const TMPXItemId& iid0 = path->Id(0);
       
   367                     const TMPXItemId& iid1 = path->Id(1);
       
   368                     if(iid0 == KPodcastingCollectionID && iid1 == 4) //EBrowseNotPlayed
       
   369                         {
       
   370                         path->Back();
       
   371                         iViewUtility->PushDefaultHistoryL();
       
   372                         iCollectionUtility->Collection().OpenL(*path);
       
   373                         handled = ETrue;
       
   374                         }
       
   375                     }
       
   376                 CleanupStack::PopAndDestroy(path);
       
   377                 }
       
   378             if(!handled)
       
   379                 {
       
   380                 CMPXCommonPlaybackViewImp::HandleCommandL( aCommand );
       
   381                 }
       
   382             break;
       
   383             }
       
   384         case EMPXPbvCmdPodcastDetails:
       
   385             {
       
   386             CMPXCommonPlaybackViewImp::LaunchFileDetailsDialogL();
       
   387 			break;
       
   388             } 
       
   389         default:
       
   390             {
       
   391             CMPXCommonPlaybackViewImp::HandleCommandL( aCommand );
       
   392             break;
       
   393             }
       
   394         }
       
   395     }
       
   396 
       
   397 // ---------------------------------------------------------------------------
       
   398 // From CAknView
       
   399 // Handles a view activation.
       
   400 // ---------------------------------------------------------------------------
       
   401 //
       
   402 void CMPXPodcastPlaybackViewImp::DoActivateL(
       
   403     const TVwsViewId& aPrevViewId,
       
   404     TUid aCustomMessageId,
       
   405     const TDesC8& aCustomMessage )
       
   406     {
       
   407     MPX_FUNC( "CMPXPodcastPlaybackViewImp::DoActivateL()" );
       
   408 
       
   409     if ( !iContainer )
       
   410         {
       
   411         if ( !iPlaybackViewLayout )
       
   412             {
       
   413             iPlaybackViewLayout = CMPXPodcastPlaybackViewLayout::NewL();
       
   414             }
       
   415         iContainer = new ( ELeave ) CMPXPodcastPlaybackViewContainer(
       
   416             this,
       
   417             this,
       
   418             iPlaybackViewLayout );
       
   419         iContainer->SetMopParent( this );
       
   420         iContainer->ConstructL( ClientRect() );
       
   421         AppUi()->AddToStackL( *this, iContainer );
       
   422         }
       
   423 
       
   424     CMPXCommonPlaybackViewImp::DoActivateL( aPrevViewId , aCustomMessageId, aCustomMessage );
       
   425     UpdateMiddleSoftKeyDisplayL();
       
   426     }
       
   427 
       
   428 // -----------------------------------------------------------------------------
       
   429 // CMPXPodcastPlaybackViewImp::PrepareStatusPaneForExitingViewL
       
   430 // -----------------------------------------------------------------------------
       
   431 //
       
   432 void CMPXPodcastPlaybackViewImp::PrepareStatusPaneForExitingViewL()
       
   433     {
       
   434     if ( StatusPane()->CurrentLayoutResId() !=
       
   435          R_AVKON_STATUS_PANE_LAYOUT_USUAL)
       
   436         {
       
   437         StatusPane()->SwitchLayoutL(R_AVKON_STATUS_PANE_LAYOUT_USUAL);
       
   438         }
       
   439     }
       
   440 // -----------------------------------------------------------------------------
       
   441 // From MAknToolbarObserver
       
   442 // Used to change toolbar settings before toolbar becomes visible
       
   443 // -----------------------------------------------------------------------------
       
   444 //
       
   445 void CMPXPodcastPlaybackViewImp::DynInitToolbarL(TInt aResourceId, CAknToolbar* aToolbar)
       
   446     {
       
   447     if (aResourceId == R_MPX_PBV_TOUCH_TOOLBAR)
       
   448         {
       
   449         // Put initializations here to take effect before toolbar is shown
       
   450         UpdateToolbarL();
       
   451         aToolbar->UpdateBackground();
       
   452        }
       
   453     }
       
   454 
       
   455 // -----------------------------------------------------------------------------
       
   456 // From MAknToolbarObserver
       
   457 // Handles toolbar events
       
   458 // -----------------------------------------------------------------------------
       
   459 //
       
   460 void CMPXPodcastPlaybackViewImp::OfferToolbarEventL( TInt aCommandId )
       
   461     {
       
   462     TInt commandId = aCommandId;
       
   463     TInt eventModifiers = iToolbar->EventModifiers();
       
   464     if ( eventModifiers == CAknToolbar::ELongPress )
       
   465         {
       
   466         if ( aCommandId == EMPXPbvCmdNextListItem )
       
   467             {
       
   468             commandId = EMPXPbvCmdSeekForward;
       
   469             }
       
   470         else if ( aCommandId == EMPXPbvCmdPreviousListItem )
       
   471             {
       
   472             commandId = EMPXPbvCmdSeekBackward;
       
   473             }
       
   474         }
       
   475     else if ( eventModifiers == CAknToolbar::ELongPressEnded )
       
   476         {
       
   477         if ( aCommandId == EMPXPbvCmdNextListItem || aCommandId == EMPXPbvCmdPreviousListItem )
       
   478             {
       
   479             commandId = EMPXPbvCmdEndSeek;
       
   480             }
       
   481         }
       
   482 
       
   483     CAknView::ProcessCommandL( commandId );
       
   484     }
       
   485 
       
   486 // ---------------------------------------------------------------------------
       
   487 // Handle playback message.
       
   488 // ---------------------------------------------------------------------------
       
   489 //
       
   490 void CMPXPodcastPlaybackViewImp::DoHandlePlaybackMessageL(
       
   491     const CMPXMessage& aMessage )
       
   492     {
       
   493     MPX_DEBUG1( "CMPXPodcastPlaybackViewImp::DoHandlePlaybackMessageL");
       
   494 
       
   495     TMPXMessageId id( *aMessage.Value<TMPXMessageId>( KMPXMessageGeneralId ) );
       
   496     if ( KMPXMessageGeneral == id )
       
   497         {
       
   498         TInt type( *aMessage.Value<TInt>( KMPXMessageGeneralType ) );
       
   499         TInt data( *aMessage.Value<TInt>( KMPXMessageGeneralData ) );
       
   500         switch ( *aMessage.Value<TInt>( KMPXMessageGeneralEvent ) )
       
   501             {
       
   502             case TMPXPlaybackMessage::EStateChanged:
       
   503                 UpdateMiddleSoftKeyDisplayL();
       
   504                 UpdateToolbarL();
       
   505                 break;
       
   506 
       
   507             default:
       
   508                 break;
       
   509             }
       
   510         }
       
   511     CMPXCommonPlaybackViewImp::DoHandlePlaybackMessageL (aMessage);
       
   512     }
       
   513 
       
   514 // ---------------------------------------------------------------------------
       
   515 // Updates the middle toolbar button
       
   516 // ---------------------------------------------------------------------------
       
   517 //
       
   518 void CMPXPodcastPlaybackViewImp::UpdateToolbarL()
       
   519     {
       
   520     MPX_FUNC("CMPXPodcastPlaybackViewImp::UpdateToolbar");
       
   521 
       
   522     if ( AknLayoutUtils::PenEnabled() )
       
   523         {
       
   524         if ( iToolbar )
       
   525             {
       
   526             CAknButton* pausePlayControl;
       
   527             pausePlayControl = (CAknButton*)(iToolbar->ComponentControl( 1 ));
       
   528             MMPXSource* s = iPlaybackUtility->Source();
       
   529             if ( s )
       
   530                 {
       
   531                 CMPXCollectionPlaylist* playlist = s->PlaylistL();
       
   532                 if ( playlist )
       
   533                     {
       
   534                     CleanupStack::PushL( playlist );
       
   535                     if ( playlist->Count() > 0 && pausePlayControl )
       
   536                         {
       
   537                         TMPXPlaybackState state = iPlaybackUtility->StateL();
       
   538                         if ((state == EPbStateInitialising) || (state == EPbStatePlaying))
       
   539                            {
       
   540                            pausePlayControl->SetCurrentState(0, ETrue);
       
   541                            }
       
   542                         else
       
   543                            {
       
   544                            pausePlayControl->SetCurrentState(1, ETrue);
       
   545                            }
       
   546                         }
       
   547                     CleanupStack::PopAndDestroy( playlist );
       
   548                     }
       
   549                 }
       
   550             }
       
   551         }
       
   552     }
       
   553 
       
   554 //  End of File