browserplugins/browseraudiovideoplugin/src/BavpMediaRecognizer.cpp
changeset 51 48e827313edd
parent 37 481242ead638
child 53 f427d27b98d8
equal deleted inserted replaced
37:481242ead638 51:48e827313edd
     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 the License "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 CBavpMediaRecognizer
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDE FILES
       
    20 #include <eikenv.h>
       
    21 #include <bautils.h>
       
    22 #include <mmf/server/mmfdatasourcesink.hrh>
       
    23 #include <mmf/common/mmfcontrollerpluginresolver.h>
       
    24 
       
    25 #include "BavpMediaRecognizer.h"
       
    26 #include "BavpLogger.h"
       
    27 
       
    28 // CONSTANTS
       
    29 _LIT8(KDataTypeRAM, "audio/x-pn-realaudio-plugin");
       
    30 _LIT8(KDataTypeSDP, "application/sdp");
       
    31 _LIT8(KDataTypePlaylist, "audio/mpegurl");
       
    32 _LIT8(KDataTypeRNG, "application/vnd.nokia.ringing-tone"); 
       
    33 _LIT8(KDataTypeMp3, "audio/mp3"); 
       
    34 _LIT8(KDataTypeXmp3, "audio/x-mp3"); 
       
    35 _LIT8(KDataTypeAudio3gp, "audio/3gpp");
       
    36 
       
    37 #if defined(BRDO_ASX_FF)
       
    38 _LIT8(KDataTypeWvx, "video/x-ms-wvx");
       
    39 _LIT8(KDataTypeWax, "audio/x-ms-wax");
       
    40 _LIT8(KDataTypeAsx, "video/x-ms-asx");
       
    41 #endif // BRDO_ASX_FF
       
    42 
       
    43 _LIT(KUrlRtsp, "rtsp:");
       
    44 
       
    45 const TInt KDefaultBufferSize = 1000;
       
    46  
       
    47 // _LIT(KRamFileExtension,".ram");
       
    48 
       
    49 // ============================ MEMBER FUNCTIONS ===============================
       
    50 
       
    51 // -----------------------------------------------------------------------------
       
    52 // CBavpMediaRecognizer::CBavpMediaRecognizer
       
    53 // C++ default constructor can NOT contain any code, that
       
    54 // might leave.
       
    55 // -----------------------------------------------------------------------------
       
    56 CBavpMediaRecognizer::CBavpMediaRecognizer()
       
    57     {
       
    58     }
       
    59 
       
    60 // -----------------------------------------------------------------------------
       
    61 // CBavpMediaRecognizer::ConstructL
       
    62 // Symbian 2nd phase constructor can leave.
       
    63 // -----------------------------------------------------------------------------
       
    64 void CBavpMediaRecognizer::ConstructL()
       
    65     {
       
    66     User::LeaveIfError( iRecognizer.Connect() );
       
    67     if ( iRecognizer.GetMaxDataBufSize( iBufSize) || iBufSize <= 0 )
       
    68         {
       
    69         iBufSize = KDefaultBufferSize;
       
    70         }
       
    71     CreateVideoFormatsArrayL();
       
    72     CreateAudioFormatsArrayL();
       
    73     }
       
    74 
       
    75 // -----------------------------------------------------------------------------
       
    76 // CBavpMediaRecognizer::NewL
       
    77 // Two-phased constructor.
       
    78 // -----------------------------------------------------------------------------
       
    79 CBavpMediaRecognizer* CBavpMediaRecognizer::NewL()
       
    80     {
       
    81     CBavpMediaRecognizer* self = new( ELeave ) CBavpMediaRecognizer; 
       
    82     CleanupStack::PushL( self );
       
    83     self->ConstructL();
       
    84     CleanupStack::Pop();
       
    85     return self;
       
    86     }
       
    87 
       
    88 // -----------------------------------------------------------------------------
       
    89 // CBavpMediaRecognizer::~CBavpMediaRecognizer   
       
    90 // Destructor
       
    91 // -----------------------------------------------------------------------------
       
    92 CBavpMediaRecognizer::~CBavpMediaRecognizer()
       
    93     {
       
    94     iVideoControllers.ResetAndDestroy();
       
    95     iAudioControllers.ResetAndDestroy();
       
    96     iRecognizer.Close();
       
    97     iFileHandle.Close();
       
    98     }
       
    99 
       
   100 // -----------------------------------------------------------------------------
       
   101 //  CBavpMediaRecognizer::IdentifyMediaTypeL
       
   102 // -----------------------------------------------------------------------------
       
   103 TBavpMediaType
       
   104 CBavpMediaRecognizer::IdentifyMediaTypeL( const TDesC& aMediaName, 
       
   105                                           TBool aIncludeUrls )
       
   106     {
       
   107     TBavpMediaType ret = EUnidentified;
       
   108 
       
   109     if ( BaflUtils::FileExists( CEikonEnv::Static()->FsSession(), aMediaName ) )
       
   110         {
       
   111         TDataRecognitionResult fileRecognitionResult;
       
   112         RecognizeFileL( aMediaName, fileRecognitionResult );
       
   113         
       
   114         if ( !fileRecognitionResult.iDataType.Des8().CompareF( KDataTypeSDP ) )
       
   115             {
       
   116             ret = ELocalSdpFile;
       
   117             Log( EFalse, _L("CBavpMediaRecognizer::IdentifyMediaTypeL - ELocalSdpFile") );
       
   118             }
       
   119         
       
   120         if ( ret == EUnidentified && 
       
   121              !fileRecognitionResult.iDataType.Des8().CompareF( KDataTypePlaylist ) )
       
   122             {
       
   123             ret = ELocalAudioPlaylist;
       
   124             Log( EFalse, _L("CBavpMediaRecognizer::IdentifyMediaTypeL - ELocalAudioPlaylist") );
       
   125             }
       
   126         
       
   127         if ( ret == EUnidentified && 
       
   128              FileHasAudioSupport( aMediaName, fileRecognitionResult ) || 
       
   129              !fileRecognitionResult.iDataType.Des8().CompareF( KDataTypeRNG ) ||
       
   130              !fileRecognitionResult.iDataType.Des8().CompareF( KDataTypeMp3 ) ||
       
   131              !fileRecognitionResult.iDataType.Des8().CompareF( KDataTypeXmp3 ) ||
       
   132              !fileRecognitionResult.iDataType.Des8().CompareF( KDataTypeAudio3gp ) ) 
       
   133             {
       
   134             ret = ELocalAudioFile; 
       
   135             Log( EFalse, _L("CBavpMediaRecognizer::IdentifyMediaTypeL - ELocalAudioFile") );
       
   136             }
       
   137         
       
   138         if ( ret == EUnidentified && 
       
   139              FileHasVideoSupport( aMediaName, fileRecognitionResult ) )
       
   140             {
       
   141             ret = ELocalVideoFile;
       
   142             Log( EFalse, _L("CBavpMediaRecognizer::IdentifyMediaTypeL - ELocalVideoFile") );
       
   143             }
       
   144         
       
   145         if ( ret == EUnidentified && 
       
   146              !fileRecognitionResult.iDataType.Des8().CompareF( KDataTypeRAM ) )
       
   147             {
       
   148             ret = ELocalRamFile;
       
   149             Log( EFalse, _L("CBavpMediaRecognizer::IdentifyMediaTypeL - ELocalRamFile") );
       
   150             }
       
   151 #if defined(BRDO_ASX_FF)
       
   152         if ( ret == EUnidentified && 
       
   153              !fileRecognitionResult.iDataType.Des8().CompareF( KDataTypeWvx ) ||
       
   154              !fileRecognitionResult.iDataType.Des8().CompareF( KDataTypeWax ) ||
       
   155              !fileRecognitionResult.iDataType.Des8().CompareF( KDataTypeAsx ))
       
   156             {
       
   157             ret = ELocalAsxFile;
       
   158             Log( EFalse, _L("CBavpMediaRecognizer::IdentifyMediaTypeL - ELocalAsxFile") );
       
   159             }
       
   160 #endif // BRDO_ASX_FF
       
   161         }
       
   162     else
       
   163         {
       
   164         if ( aIncludeUrls && ValidUrl( aMediaName ) )
       
   165             {
       
   166             ret = EUrl;
       
   167             Log( EFalse, _L("CBavpMediaRecognizer::IdentifyMediaTypeL - EUrl") );
       
   168             }
       
   169         }
       
   170     return ret;
       
   171     }
       
   172 
       
   173 // -----------------------------------------------------------------------------
       
   174 //  CBavpMediaRecognizer::IdentifyMediaTypeL 
       
   175 // -----------------------------------------------------------------------------
       
   176 TBavpMediaType 
       
   177 CBavpMediaRecognizer::IdentifyMediaTypeL( const TDesC& aMediaName, 
       
   178                                           RFile& aFile,
       
   179                                           TBool aIncludeUrls )
       
   180     {
       
   181     if( aFile.SubSessionHandle() )
       
   182         {
       
   183         User::LeaveIfError( iFileHandle.Duplicate( aFile ) ); 
       
   184         }
       
   185     
       
   186     TBavpMediaType ret = EUnidentified;
       
   187 
       
   188     if ( BaflUtils::FileExists( CEikonEnv::Static()->FsSession(), aMediaName ) || FileHandleExists() ) 
       
   189         {
       
   190         TDataRecognitionResult fileRecognitionResult;
       
   191         RecognizeFileL( aMediaName, fileRecognitionResult );
       
   192         
       
   193         if ( !fileRecognitionResult.iDataType.Des8().CompareF( KDataTypeSDP ) )
       
   194             {
       
   195             ret = ELocalSdpFile;
       
   196             Log( EFalse, _L("CBavpMediaRecognizer::IdentifyMediaTypeL - ELocalSdpFile") );
       
   197             }
       
   198             
       
   199         if ( ret == EUnidentified && 
       
   200              !fileRecognitionResult.iDataType.Des8().CompareF( 
       
   201              KDataTypePlaylist ) )
       
   202             {
       
   203             ret = ELocalAudioPlaylist;
       
   204             Log( EFalse, _L("CBavpMediaRecognizer::IdentifyMediaTypeL - ELocalAudioPlaylist") );
       
   205             }
       
   206         
       
   207         if ( ret == EUnidentified && 
       
   208              FileHasAudioSupport( aMediaName, fileRecognitionResult ) || 
       
   209              !fileRecognitionResult.iDataType.Des8().CompareF( KDataTypeRNG ) ||
       
   210              !fileRecognitionResult.iDataType.Des8().CompareF( KDataTypeMp3 ) ||
       
   211              !fileRecognitionResult.iDataType.Des8().CompareF( KDataTypeXmp3 ) ||
       
   212              !fileRecognitionResult.iDataType.Des8().CompareF( KDataTypeAudio3gp ) ) 
       
   213             {
       
   214             ret = ELocalAudioFile; 
       
   215             Log( EFalse, _L("CBavpMediaRecognizer::IdentifyMediaTypeL - ELocalAudioFile") );
       
   216             }
       
   217 
       
   218         if ( ret == EUnidentified && 
       
   219              FileHasVideoSupport( aMediaName, fileRecognitionResult ) )
       
   220             {
       
   221             ret = ELocalVideoFile;
       
   222             Log( EFalse, _L("CBavpMediaRecognizer::IdentifyMediaTypeL - ELocalVideoFile") );
       
   223             }
       
   224 
       
   225         if ( ret == EUnidentified && 
       
   226              !fileRecognitionResult.iDataType.Des8().CompareF( KDataTypeRAM ) )
       
   227             {
       
   228             ret = ELocalRamFile;
       
   229             Log( EFalse, _L("CBavpMediaRecognizer::IdentifyMediaTypeL - ELocalRamFile") );
       
   230             }
       
   231 #if defined(BRDO_ASX_FF)
       
   232         if ( ret == EUnidentified && 
       
   233              !fileRecognitionResult.iDataType.Des8().CompareF( KDataTypeWvx ) ||
       
   234              !fileRecognitionResult.iDataType.Des8().CompareF( KDataTypeWax ) ||
       
   235              !fileRecognitionResult.iDataType.Des8().CompareF( KDataTypeAsx ) )
       
   236             {
       
   237             ret = ELocalAsxFile;
       
   238             Log( EFalse, _L("CBavpMediaRecognizer::IdentifyMediaTypeL - ELocalAsxFile") );
       
   239             }
       
   240 #endif // BRDO_ASX_FF
       
   241         }
       
   242     else
       
   243         {
       
   244         if (aIncludeUrls && ValidUrl(aMediaName))
       
   245             {
       
   246             ret = EUrl;
       
   247             }
       
   248         }
       
   249     return ret;
       
   250     }
       
   251 
       
   252 // -----------------------------------------------------------------------------
       
   253 // CBavpMediaRecognizer::MimeTypeL
       
   254 // -----------------------------------------------------------------------------
       
   255 TBuf<KMaxDataTypeLength>
       
   256 CBavpMediaRecognizer::MimeTypeL( const TDesC& aLocalFile )
       
   257     {
       
   258     TDataRecognitionResult fileRecognitionResult;
       
   259     RecognizeFileL( aLocalFile,fileRecognitionResult );
       
   260     
       
   261     if ( fileRecognitionResult.iConfidence >= CApaDataRecognizerType::EPossible )
       
   262         {
       
   263         return fileRecognitionResult.iDataType.Des();
       
   264         }
       
   265         
       
   266     return KNullDesC();
       
   267     }
       
   268 
       
   269 // -----------------------------------------------------------------------------
       
   270 // CBavpMediaRecognizer::FileHasVideoSupport
       
   271 // -----------------------------------------------------------------------------
       
   272 TBool CBavpMediaRecognizer::FileHasVideoSupport( const TDesC& /*aFileName*/, 
       
   273                                 TDataRecognitionResult& aFileRecognitionResult)
       
   274     {
       
   275     // Try with mime type
       
   276     // We have a good quess -> go with mime type
       
   277     if ( aFileRecognitionResult.iConfidence >= CApaDataRecognizerType::EPossible )
       
   278         {
       
   279         for (TInt i = 0 ; i < iVideoControllers.Count() ; i++)
       
   280             {           
       
   281             RMMFFormatImplInfoArray formats = 
       
   282                         iVideoControllers[i]->PlayFormats();
       
   283                 for ( TInt j = 0; j < formats.Count() ; j++ )
       
   284                     { 
       
   285                     if ( formats[j]->SupportsMimeType( 
       
   286                             aFileRecognitionResult.iDataType.Des8() ) )
       
   287                         return ETrue;
       
   288                     }
       
   289             }
       
   290         } 
       
   291     return EFalse;
       
   292     }
       
   293 
       
   294 // -----------------------------------------------------------------------------
       
   295 // CBavpMediaRecognizer::FileHasAudioSupport
       
   296 // -----------------------------------------------------------------------------
       
   297 TBool CBavpMediaRecognizer::FileHasAudioSupport(const TDesC& aFileName, 
       
   298                                TDataRecognitionResult& aFileRecognitionResult )
       
   299     {
       
   300      // try with mime type
       
   301     // we have a good quess -> gogo with mime type
       
   302     if (aFileRecognitionResult.iConfidence >= CApaDataRecognizerType::EPossible)
       
   303         {
       
   304         for (TInt i = 0 ; i < iAudioControllers.Count() ; i++)
       
   305             {           
       
   306             RMMFFormatImplInfoArray formats = 
       
   307                     iAudioControllers[i]->PlayFormats();
       
   308                 for (TInt j = 0; j < formats.Count() ; j++)
       
   309                     { 
       
   310                     if ( formats[j]->SupportsMimeType( 
       
   311                             aFileRecognitionResult.iDataType.Des8() ) )
       
   312                         return ETrue;
       
   313                     }
       
   314             }
       
   315         }
       
   316  
       
   317     // we can't quess -> try with file extension
       
   318     else
       
   319         {
       
   320         TParsePtrC parser(aFileName);
       
   321         TBuf8<KMaxFileName> fileExtension;
       
   322         fileExtension.Copy(parser.Ext());
       
   323         for (TInt i = 0 ; i < iVideoControllers.Count() ; i++)
       
   324             {
       
   325             RMMFFormatImplInfoArray formats = 
       
   326                     iAudioControllers[i]->PlayFormats();
       
   327             for (TInt j = 0; j < formats.Count() ; j++)
       
   328                 {
       
   329                 if (formats[j]->SupportsFileExtension(fileExtension))
       
   330                     return ETrue;
       
   331                 }
       
   332             }
       
   333         }
       
   334    
       
   335     return EFalse;
       
   336     }
       
   337 
       
   338 // -----------------------------------------------------------------------------
       
   339 // CBavpMediaRecognizer::ValidUrl
       
   340 // -----------------------------------------------------------------------------
       
   341 TBool CBavpMediaRecognizer::ValidUrl(const TDesC& aUrl)
       
   342     {
       
   343     TBool ret = EFalse;
       
   344     if (aUrl.Find(KUrlRtsp) == 0)
       
   345         {
       
   346         ret = ETrue;
       
   347         }
       
   348     return ret;
       
   349     }
       
   350 
       
   351 // -----------------------------------------------------------------------------
       
   352 // CBavpMediaRecognizer::MimeTypeL
       
   353 // -----------------------------------------------------------------------------
       
   354 TBuf<KMaxDataTypeLength> CBavpMediaRecognizer::MimeTypeL(RFile& aFile)
       
   355     {
       
   356     if( aFile.SubSessionHandle() )
       
   357         {
       
   358         // Preferred
       
   359         User::LeaveIfError( iFileHandle.Duplicate( aFile ) ); 
       
   360         }
       
   361 
       
   362     // If new handle is not valid, old might still be
       
   363     if ( !FileHandleExists() )
       
   364         {
       
   365         User::Leave( KErrBadHandle );
       
   366         }
       
   367 
       
   368     TDataRecognitionResult fileRecognitionResult;
       
   369     RecognizeFileL( KNullDesC(), fileRecognitionResult );
       
   370     
       
   371     if (fileRecognitionResult.iConfidence >= CApaDataRecognizerType::EPossible)
       
   372         {
       
   373         return fileRecognitionResult.iDataType.Des();
       
   374         }
       
   375     return KNullDesC();
       
   376     }
       
   377 
       
   378 // -----------------------------------------------------------------------------
       
   379 // CBavpMediaRecognizer::CreateVideoFormatsArrayL
       
   380 // -----------------------------------------------------------------------------
       
   381 void CBavpMediaRecognizer::CreateVideoFormatsArrayL()
       
   382     {
       
   383     CMMFControllerPluginSelectionParameters* cSelect = 
       
   384             CMMFControllerPluginSelectionParameters::NewLC();
       
   385     
       
   386     CMMFFormatSelectionParameters* fSelect = 
       
   387             CMMFFormatSelectionParameters::NewLC();
       
   388     
       
   389     // Set the play and record format selection parameters to be blank.  
       
   390     // - format support is only retrieved if requested.
       
   391     cSelect->SetRequiredPlayFormatSupportL(*fSelect);
       
   392     
       
   393     // Set the media ids
       
   394     RArray<TUid> mediaIds;
       
   395     CleanupClosePushL(mediaIds);
       
   396     User::LeaveIfError(mediaIds.Append(KUidMediaTypeVideo));
       
   397     
       
   398     // Get plugins that support at least video
       
   399     cSelect->SetMediaIdsL( mediaIds, 
       
   400             CMMFPluginSelectionParameters::EAllowOtherMediaIds );
       
   401     
       
   402     // iVideoControllers contains now all plugins that support at least video
       
   403     cSelect->ListImplementationsL(iVideoControllers);           
       
   404     
       
   405     // Clean up
       
   406     CleanupStack::PopAndDestroy( 3 ); // fSelect, cSelect, mediaIds
       
   407     }
       
   408 
       
   409 // -----------------------------------------------------------------------------
       
   410 // CBavpMediaRecognizer::CreateAudioFormatsArrayL
       
   411 // -----------------------------------------------------------------------------
       
   412 void CBavpMediaRecognizer::CreateAudioFormatsArrayL()
       
   413     {
       
   414     CMMFControllerPluginSelectionParameters* cSelect = 
       
   415             CMMFControllerPluginSelectionParameters::NewLC();
       
   416 
       
   417     CMMFFormatSelectionParameters* fSelect = 
       
   418             CMMFFormatSelectionParameters::NewLC();
       
   419 
       
   420     // Set the play and record format selection parameters to be blank.  
       
   421     // - format support is only retrieved if requested.
       
   422     cSelect->SetRequiredPlayFormatSupportL( *fSelect );
       
   423 
       
   424     // Set the media ids
       
   425     RArray<TUid> mediaIds;
       
   426     CleanupClosePushL( mediaIds );
       
   427     User::LeaveIfError( mediaIds.Append(KUidMediaTypeAudio) );
       
   428 
       
   429     // Get plugins that supports audio only
       
   430     cSelect->SetMediaIdsL( mediaIds, 
       
   431             CMMFPluginSelectionParameters::EAllowOnlySuppliedMediaIds ); 
       
   432 
       
   433     // iAudioControllers contains now all audio plugins that 
       
   434     // support at least audio.
       
   435     cSelect->ListImplementationsL( iAudioControllers );           
       
   436 
       
   437     // Clean up
       
   438     CleanupStack::PopAndDestroy( 3 ); // fSelect, cSelect, mediaIds
       
   439     }
       
   440 
       
   441 // -----------------------------------------------------------------------------
       
   442 // CBavpMediaRecognizer::RecognizeFileL
       
   443 // -----------------------------------------------------------------------------
       
   444 void CBavpMediaRecognizer::RecognizeFileL( const TDesC& aFileName, 
       
   445                                            TDataRecognitionResult& aResult )
       
   446     {
       
   447     aResult.Reset();
       
   448     HBufC8* fBuf = HBufC8::NewLC( iBufSize ); // fBuf in CS
       
   449     TPtr8 fileBuf = fBuf->Des();
       
   450  
       
   451     // Recognize file
       
   452     if ( FileHandleExists() )
       
   453         {
       
   454         User::LeaveIfError( iRecognizer.RecognizeData( iFileHandle, aResult ) );
       
   455         }
       
   456     else
       
   457         {
       
   458         // Read file
       
   459         User::LeaveIfError( ReadFile( aFileName, fileBuf ) );   
       
   460         User::LeaveIfError( iRecognizer.RecognizeData( aFileName, fileBuf, aResult ) ); 
       
   461         }
       
   462    
       
   463     CleanupStack::PopAndDestroy(); // fBuf
       
   464     }
       
   465 
       
   466 // -----------------------------------------------------------------------------
       
   467 // CBavpMediaRecognizer::ReadFile
       
   468 // -----------------------------------------------------------------------------
       
   469 TInt CBavpMediaRecognizer::ReadFile( const TDesC& aFileName, TDes8& aBuf )
       
   470     {
       
   471     RFile file;
       
   472     TInt err;
       
   473 
       
   474     if ( FileHandleExists() )
       
   475         {
       
   476         err = file.Duplicate( iFileHandle ); 
       
   477         }
       
   478     else
       
   479         {
       
   480         err = file.Open( CEikonEnv::Static()->FsSession(), aFileName,
       
   481                          EFileRead | EFileShareAny );
       
   482         if ( err ) 
       
   483             {
       
   484             err = file.Open( CEikonEnv::Static()->FsSession(), aFileName,
       
   485                              EFileRead | EFileShareReadersOnly );
       
   486             } 
       
   487         }
       
   488 
       
   489     if ( err )
       
   490         {
       
   491         // If file does not exist
       
   492         return err;
       
   493         }
       
   494 
       
   495     // Read the beginning of the file
       
   496     err = file.Read( 0, aBuf, iBufSize );
       
   497     file.Close();
       
   498 
       
   499     return err;
       
   500     }
       
   501 
       
   502 // -----------------------------------------------------------------------------
       
   503 // CBavpMediaRecognizer::FileHandleExists
       
   504 // -----------------------------------------------------------------------------
       
   505 TBool CBavpMediaRecognizer::FileHandleExists()
       
   506     {
       
   507     TInt size(0);
       
   508     TInt err(0);
       
   509 
       
   510     if ( iFileHandle.SubSessionHandle() )
       
   511         {
       
   512         err = iFileHandle.Size( size );
       
   513         }
       
   514     
       
   515     return ( !err && size ) ? ETrue : EFalse;
       
   516     }
       
   517 
       
   518 //  End of File