profilesapplication/Profiles/ProfileApp/SettingsViewSrc/CProfileToneHandler.cpp
branchRCL_3
changeset 19 cd54903d48da
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/profilesapplication/Profiles/ProfileApp/SettingsViewSrc/CProfileToneHandler.cpp	Wed Sep 01 12:30:29 2010 +0100
@@ -0,0 +1,681 @@
+/*
+* Copyright (c) 2002-2006 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  A helper interface to be used by S60 applications for
+*                setting ringing and alert tones for different profiles.
+*                Registers DRM protected tones as automated content
+*                and removes old content from automated content list.
+*                Shows a content activation query if necessary.
+*
+*/
+
+
+
+// CLASS HEADER
+#include    "cprofiletonehandler.h"
+
+// INTERNAL INCLUDES
+#include	"ProfileMmfInfoUtility.h"
+
+// EXTERNAL INCLUDES
+#include 	<centralrepository.h>
+#include    <ProfileEngineDomainCRKeys.h> // KProEngRingingToneMaxSize
+#include    <bautils.h> // BaflUtils
+#include    <apgcli.h> // RApaLsSession
+#include    <coemain.h> // CCoeEnv
+#include    <aknnotewrappers.h> // CAknInformationNote
+#include    <ConeResLoader.h> // RConeResourceLoader
+#include	<StringLoader.h>
+#include    <MProfileEngineExtended.h>
+#include    <MProfilesLocalFeatures.h>
+#include    <MProfileExtended.h>
+#include    <MProfileSetExtraTones.h>
+#include    <MProfileSetTones.h>
+#include    <MProfileExtraTones.h>
+#include    <MProfileTones.h>
+#include    <MProfilesNamesArray.h>
+#include    <MProfileName.h>
+#include    <MProfileUtilitySingleton.h>
+#include    <profilesettingsview.rsg>
+#include    <AknGlobalNote.h>
+#include    <f32file.h>
+
+namespace
+	{
+	// CONSTANTS
+	_LIT( KProfileSilentTone,     "Z:No_Sound.wav" );
+	_LIT( KProfileAudioMimeType,  "audio" );
+	_LIT( KProfileRngMimeType,    "application/vnd.nokia.ringing-tone" );
+
+	_LIT( KProfileCommonVideoType, "video/*" );
+	_LIT( KProfileRMVideoMimeType, "application/vnd.rn-realmedia" );
+	_LIT( KProfileRMVideoMimeType2, "application/x-pn-realmedia" );
+	_LIT( KProfileSDPVideoMimeType, "application/sdp" );
+	_LIT( KProfilePlainTextType, "text/plain" );
+	// The filename of the resource file
+	_LIT( KProfileResourceFileName, "Z:ProfileSettingsView.RSC" );
+	}
+
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CProfileToneHandler::CProfileToneHandler
+// C++ default constructor can NOT contain any code, that might leave.
+// -----------------------------------------------------------------------------
+//
+CProfileToneHandler::CProfileToneHandler()
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CProfileToneHandler::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CProfileToneHandler::ConstructL()
+    {
+    DrmConstructL();
+    GetMaxToneFileSizeL();
+    User::LeaveIfError( iFs.Connect() );
+    iProfileEngine = CreateProfileEngineExtendedL( &iFs );
+    // NB. Singleton must be released in the destructor:
+    iProfilesFeatures = &( ProfileUtilityInstanceL().ProfilesLocalFeatures() );
+        
+    User::LeaveIfError( iSSSettings.Open() );
+    iSSSettings.Get( ESSSettingsAls, iAlternateLineSetting ); // ignore errors
+    iSSSettings.Register( ESSSettingsAls, *this ); // ignore errors
+    }
+
+// -----------------------------------------------------------------------------
+// CProfileToneHandler::NewLC
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CProfileToneHandler* CProfileToneHandler::NewLC()
+    {
+    CProfileToneHandler* self = new( ELeave ) CProfileToneHandler();
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CProfileToneHandler::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CProfileToneHandler* CProfileToneHandler::NewL()
+    {
+    CProfileToneHandler* self = CProfileToneHandler::NewLC();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// Destructor
+CProfileToneHandler::~CProfileToneHandler()
+    {
+    iSSSettings.Close();
+    iFs.Close();
+    if( iProfileEngine )
+        {
+        iProfileEngine->Release();
+        }
+        
+    if ( iProfilesFeatures )
+        {
+        ReleaseProfileUtility();    
+        }
+    
+    ReleaseDrm();
+    }
+
+// -----------------------------------------------------------------------------
+// CProfileToneHandler::SetActiveProfileRingingToneL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CProfileToneHandler::SetActiveProfileRingingToneL(
+    const TDesC& aFileName )
+    {
+    // Find out the ID of the active profile
+    TInt activeProfileId(
+        User::LeaveIfError( iProfileEngine->ActiveProfileId() ) );
+
+    return SetProfileToneL(
+        activeProfileId, EProfileRingingToneSetting, aFileName );
+    }
+
+// -----------------------------------------------------------------------------
+// CProfileToneHandler::SetProfileToneL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CProfileToneHandler::SetProfileToneL( TInt aProfileId,
+    TProfileTones aToneSetting, const TDesC& aFileName )
+    {
+    // Check the file which is tried to set as ringing or alert tone.
+    TInt returnValue( CheckFileL( aFileName ) );
+    returnValue = CheckResultAndProtectionL( returnValue, aFileName );
+    if( returnValue != KErrNone )
+        {
+        return returnValue;
+        }
+
+    DoSetProfileToneL( aProfileId, aToneSetting, aFileName );
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CProfileToneHandler::SetProfileToneNotCheckL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CProfileToneHandler::SetProfileToneNotCheckL( TInt aProfileId,
+                TProfileTones aToneSetting, const TDesC& aFileName )
+    {
+    DoSetProfileToneL( aProfileId, aToneSetting, aFileName );
+    return KErrNone;    
+    }
+
+// -----------------------------------------------------------------------------
+// CProfileToneHandler::SetToneForAllProfilesL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CProfileToneHandler::SetToneForAllProfilesL(
+    TProfileTones aToneSetting, const TDesC& aFileName )
+    {
+    // Check the file which is tried to set as ringing or alert tone.
+    TInt returnValue( CheckFileL( aFileName ) );
+    returnValue = CheckResultAndProtectionL( returnValue, aFileName );
+    if( returnValue != KErrNone )
+        {
+        return returnValue;
+        }
+
+    const MProfilesNamesArray* idArray = iProfileEngine->ProfilesNamesArrayLC();
+    TInt arrayCount( idArray->MdcaCount() );
+    TInt arrayIndex( 0 );
+    TInt profileId( 0 );
+    TInt activeId( iProfileEngine->ActiveProfileId() );
+
+    // Go through profiles and update tone
+    while( arrayIndex < arrayCount )
+        {
+        profileId = idArray->ProfileName( arrayIndex )->Id();
+        // Updating of the active profile will be done last to make sure that
+        // UI gets the new value of the ringing tone if settings view is active
+        // and it is containing settings of another than active profile
+        if( profileId != activeId )
+            {
+            TRAPD(r, DoSetProfileToneL( profileId, aToneSetting, aFileName ));
+            // Filter situation when profile is not allowed to be changed
+            // e.g. Drive-profile
+            if( ( r != KErrNone ) && ( r != KErrAccessDenied ) )
+                {
+                User::Leave( r );
+                }
+            }
+        arrayIndex++;
+        }
+    CleanupStack::PopAndDestroy(); // idArray
+
+    // Update the active profile:
+    TRAPD(r, DoSetProfileToneL( activeId, aToneSetting, aFileName ));
+    // Filter situation when profile is not allowed to be changed
+    // e.g. Drive-profile
+    if( ( r != KErrNone ) && ( r != KErrAccessDenied ) )
+        {
+        User::Leave( r );
+        }
+
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CProfileToneHandler::PhoneSettingChanged
+// Callback method inherited from MSSSettingsObserver for getting events if
+// Alternate Line Service status changes.
+// -----------------------------------------------------------------------------
+//
+void CProfileToneHandler::PhoneSettingChanged(
+    TSSSettingsSetting aSetting, TInt aNewValue )
+    {
+    if( aSetting == ESSSettingsAls )
+        {
+        iAlternateLineSetting = aNewValue;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CProfileToneHandler::DoSetProfileToneL
+// -----------------------------------------------------------------------------
+//
+void CProfileToneHandler::DoSetProfileToneL( TInt aProfileId,
+    TProfileTones aToneSetting, const TDesC& aFileName )
+    {
+    // Read the settings of the profile in question
+    MProfileExtended* profile = iProfileEngine->ProfileLC( aProfileId );
+
+    // Get the old tone in order to remove it from the automated content list
+    TFileName oldTone( ReadToneL( *profile, aToneSetting ) );
+
+	TFileName fileName( aFileName );
+	if( fileName.Length() == 0 )
+        {
+        // If no filename is given, replace it with "No_sound.wav". This way
+        // it's possible to e.g. play vibra during incoming call.
+		TParse* fp = new(ELeave) TParse();
+		fp->Set(KProfileSilentTone, &KDC_RESOURCE_FILES_DIR, NULL);
+		fileName.Copy( fp->FullName() );
+		delete fp;
+        }
+
+    // Replace the old tone with the new tone
+    SetToneL( *profile, aToneSetting, fileName );
+
+    // Commit changes. Write the new settings to the Profiles Engine
+    iProfileEngine->CommitChangeL( *profile );
+
+    // Register file as automated content
+    TInt err( SetAutomated( aToneSetting, fileName ) );
+    if( err == KErrNone )
+        {
+        // Remove old tone from the automated content list
+        RemoveAutomated( oldTone );
+        }
+    else
+        {
+        // Put the old tone back into Profiles:
+        TRAP_IGNORE(
+                SetToneL( *profile, aToneSetting, oldTone );
+                iProfileEngine->CommitChangeL( *profile );
+                );
+        }
+
+    CleanupStack::PopAndDestroy(); // profile
+    User::LeaveIfError( err );
+    }
+
+// -----------------------------------------------------------------------------
+// CProfileToneHandler::SetToneL
+// -----------------------------------------------------------------------------
+//
+void CProfileToneHandler::SetToneL( MProfileExtended& aProfile,
+    TProfileTones aToneSetting, const TDesC& aFileName )
+    {
+    MProfileSetExtraTones& setExtraTones = aProfile.ProfileSetExtraTones();
+    MProfileSetTones& setTones = aProfile.ProfileSetTones();
+
+    switch( aToneSetting )
+        {
+        case EProfileRingingToneSetting:
+            {
+            if( iAlternateLineSetting == ESSSettingsAlsAlternate )
+                {
+                // Alternate Line Service is supported and alternate line is
+                // selected. Set as ringing tone for line 2.
+                setTones.SetRingingTone2L( aFileName );
+                }
+            else
+                {
+                // Alternate Line Service is not supported or primary line is
+                // selected. Set as ringing tone for line 1.
+                setTones.SetRingingTone1L( aFileName );
+                }
+            break;
+            }
+        case EProfileVideoCallToneSetting:
+            {
+            setExtraTones.SetVideoCallRingingToneL( aFileName );
+            break;
+            }
+        case EProfileMessageAlertToneSetting:
+            {
+            setTones.SetMessageAlertToneL( aFileName );
+            break;
+            }
+        case EProfileInstantMessageAlertToneSetting:
+            {
+            setExtraTones.SetIMMessageAlertToneL( aFileName );
+            break;
+            }
+        case EProfileEmailAlertToneSetting:
+            {
+            setExtraTones.SetEmailAlertToneL( aFileName );
+            break;
+            }
+        default:
+            {
+            User::Leave( KErrArgument );
+            break;
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CProfileToneHandler::ReadToneL
+// -----------------------------------------------------------------------------
+//
+const TDesC& CProfileToneHandler::ReadToneL( const MProfileExtended& aProfile,
+    TProfileTones aToneSetting ) const
+    {
+    const MProfileExtraTones& extraTones = aProfile.ProfileExtraTones();
+    const MProfileTones& tones = aProfile.ProfileTones();
+
+    switch( aToneSetting )
+        {
+        case EProfileRingingToneSetting:
+            {
+            if( iAlternateLineSetting == ESSSettingsAlsAlternate )
+                {
+                // Alternate Line Service is supported and alternate line is
+                // selected.
+                return tones.RingingTone2();
+                }
+            else
+                {
+                // Alternate Line Service is not supported or primary line is
+                // selected.
+                return tones.RingingTone1();
+                }
+            }
+        case EProfileVideoCallToneSetting:
+            {
+            return extraTones.VideoCallRingingTone();
+            }
+        case EProfileMessageAlertToneSetting:
+            {
+            return tones.MessageAlertTone();
+            }
+        case EProfileInstantMessageAlertToneSetting:
+            {
+            return extraTones.IMMessageAlertTone();
+            }
+        case EProfileEmailAlertToneSetting:
+            {
+            return extraTones.EmailAlertTone();
+            }
+        default:
+            {
+            User::Leave( KErrArgument );
+            break;
+            }
+        }
+    return KNullDesC;
+    }
+
+// -----------------------------------------------------------------------------
+// CProfileToneHandler::CheckFileL
+// -----------------------------------------------------------------------------
+//
+TInt CProfileToneHandler::CheckFileL( const TDesC& aFileName )
+    {
+    if( aFileName.Length() == 0 )
+        {
+        // The filename is empty, ok.
+        // It will be changed to "No_sound.wav" when writing to Profiles Engine.
+        return KErrNone;
+        }
+
+    if( !BaflUtils::FileExists( iFs, aFileName ) )
+        {
+        // The file does not exist. No good (start the dance).
+        return KErrNotFound;
+        }
+
+   	TBool isAudio( EFalse );
+	TBool isVideo( EFalse );
+
+    // The file exists. Check its data (MIME) type.
+    TBuf<KMaxDataTypeLength> dataType( DataTypeL( aFileName ) );
+    if( ( dataType.Left( KProfileAudioMimeType()
+    .Length() ).CompareF( KProfileAudioMimeType ) == 0 ) ||
+		( dataType.CompareF( KProfileRngMimeType ) == 0 ) )
+    	{
+    	isAudio = ETrue;
+    	}
+
+    if( dataType.MatchF( KProfileCommonVideoType ) == 0 ||
+		dataType.CompareF( KProfileRMVideoMimeType ) == 0 ||
+		dataType.CompareF( KProfileRMVideoMimeType2 ) == 0 ||
+		dataType.CompareF( KProfileSDPVideoMimeType ) == 0 )
+        {
+#ifdef RD_VIDEO_AS_RINGING_TONE	
+        isVideo = ETrue;
+#else
+        isVideo = EFalse;
+#endif
+        }
+
+	if( (!isAudio) && (!isVideo) && (dataType.CompareF(KProfilePlainTextType) != 0) )
+		{
+	    // The data type does not start with "audio" or video and it's not RNG file.
+    	return KErrNotSupported;
+		}
+		
+	// Check whether file is supported by MMF
+	TBuf8<KMaxDataTypeLength> tempDataType;
+	tempDataType.Copy( dataType );
+    if (!ProfileMmfInfoUtility::IsMimeTypeSupportedL(tempDataType)
+			&& !ProfileMmfInfoUtility::IsHeaderDataSupportedL(aFileName))
+		{
+		// File is not supported by MMF
+		return KErrNotSupported;
+		}
+    
+	// Operator requirement. Check if the tones of this data type are blocked:
+    if( iProfilesFeatures->IsBlockedType( dataType ) ||
+        iProfilesFeatures->IsExcludedType( dataType ) )
+        {
+        User::Leave( KErrArgument );
+        }
+
+	// Check if the tone is WMDRM protected
+	if( IsFileWMDRMProtectedL( aFileName ) )
+		{
+		return KErrPermissionDenied;
+		}
+
+    TInt result( KErrNone );
+    if( IsProtected( aFileName ) )
+        {
+        // In certain variants tones of certain MIME-types are not allowed as
+        // alert tones if they are DRM-protected, check if this is one:
+        if( iProfilesFeatures->IsBlockedProtectedType( dataType ) )
+            {
+            return KErrArgument;
+            }
+        result = CheckProtectedFileL( aFileName );
+        }
+    else
+        {
+        result = iProfilesFeatures->IsBlockedUnprotectedType( dataType ) ?
+                 KErrPermissionDenied : KErrNone;
+        }
+    return result;
+    }
+
+// -----------------------------------------------------------------------------
+// CProfileToneHandler::CheckResultAndProtectionL
+// Find out the mime type of the file
+// -----------------------------------------------------------------------------
+//
+TInt CProfileToneHandler::CheckResultAndProtectionL( TInt aResult,
+    const TDesC& aFileName )
+    {
+    if( aResult == KErrPermissionDenied || aResult == KErrNotSupported ||
+        aResult == KErrNotFound )
+        {
+        User::Leave( aResult );
+        }
+    else if( aResult != KErrNone )
+        {
+        return aResult;
+        }
+
+    // If tone file size is limited,
+    // check if this file's size exceeds this limit.
+    if ( iMaxSizeKB )
+        {
+        if ( CheckToneFileSizeL( aFileName, iMaxSizeKB ) != KErrNone )
+            {
+            ShowSizeErrorNoteL( iMaxSizeKB );
+            return KErrTooBig;
+            }
+        }
+
+    if( IsProtected( aFileName ) )
+        {
+        if( !CanSetAutomated( aFileName ) )
+            {
+            // DRM v2 content should be caught here
+            ShowErrorNoteL( R_PROFILE_TEXT_DRM_PREV_RIGHTS_SET );
+            return KErrGeneral;
+            }
+
+        // If the file in question is unactivated protected content,
+        // ask user if he/she wants to activate it.
+        if( AskAutomated( aFileName ) == KErrCancel )
+            {
+            // User doesn't want to activate unactivated protected content.
+            return KErrCancel;
+            }
+        }
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CProfileToneHandler::DataType
+// Find out the mime type of the file
+// -----------------------------------------------------------------------------
+//
+TBuf<KMaxDataTypeLength> CProfileToneHandler::DataTypeL(
+    const TDesC& aFileName ) const
+    {
+    RApaLsSession apaLsSession;
+    User::LeaveIfError( apaLsSession.Connect() );
+    CleanupClosePushL( apaLsSession );
+
+    TUid dummyUid = { 0 }; // instantiate as zero
+    TDataType dataType( dummyUid );
+    User::LeaveIfError(
+        apaLsSession.AppForDocument( aFileName, dummyUid, dataType ) );
+
+    CleanupStack::PopAndDestroy(); // apaLsSession.Close()
+    return dataType.Des();
+    }
+
+// -----------------------------------------------------------------------------
+// CProfileToneHandler::ShowErrorNoteL
+// -----------------------------------------------------------------------------
+//
+void CProfileToneHandler::ShowErrorNoteL( TInt aResourceId ) const
+    {
+    CCoeEnv* coeEnv = CCoeEnv::Static();
+    RConeResourceLoader resourceLoader( *coeEnv );
+	CleanupClosePushL( resourceLoader );
+
+	TParse* fp = new(ELeave) TParse();
+	fp->Set(KProfileResourceFileName, &KDC_RESOURCE_FILES_DIR, NULL);
+	TFileName localizedFileName( fp->FullName() );
+	delete fp;
+
+    resourceLoader.OpenL( localizedFileName );
+
+    HBufC* errorText = StringLoader::LoadLC( aResourceId );
+    CAknInformationNote* note = new( ELeave ) CAknInformationNote( EFalse );
+    note->ExecuteLD( *errorText );
+
+	// errorText
+    CleanupStack::PopAndDestroy( errorText );
+	// resourceLoader
+	CleanupStack::PopAndDestroy( );
+    }
+
+// -----------------------------------------------------------------------------
+// CProfileToneHandler::ShowSizeErrorNoteL
+// -----------------------------------------------------------------------------
+//
+void CProfileToneHandler::ShowSizeErrorNoteL( TInt aSizeLimitKB )
+    {
+    CCoeEnv* coeEnv = CCoeEnv::Static();
+    RConeResourceLoader resourceLoader( *coeEnv );
+	CleanupClosePushL( resourceLoader );
+
+	TParse* fp = new(ELeave) TParse();
+	CleanupStack::PushL( fp );
+	fp->Set( KProfileResourceFileName, &KDC_RESOURCE_FILES_DIR, NULL);
+	
+	TFileName* fileName = new( ELeave ) TFileName();
+	fileName->Copy( fp->FullName() );
+	CleanupStack::PushL( fileName );
+    resourceLoader.OpenL( *fileName );
+    CleanupStack::PopAndDestroy( fileName );
+
+    HBufC* errorText = StringLoader::LoadLC(  R_PROFILE_TEXT_TONE_MAXSIZE_ERROR, aSizeLimitKB );
+    CAknInformationNote* note = new( ELeave ) CAknInformationNote( EFalse );
+    note->ExecuteLD( *errorText );
+
+    CleanupStack::PopAndDestroy( errorText );
+    CleanupStack::PopAndDestroy( fp );
+	CleanupStack::PopAndDestroy( &resourceLoader );
+    }
+
+// -----------------------------------------------------------------------------
+// CProfileToneHandler::GetMaxToneFileSizeL
+// -----------------------------------------------------------------------------
+//
+void CProfileToneHandler::GetMaxToneFileSizeL()
+    {
+	CRepository* cenrep = CRepository::NewL( KCRUidProfileEngine );
+	CleanupStack::PushL( cenrep );
+	TInt error = cenrep->Get( KProEngRingingToneMaxSize, iMaxSizeKB );
+	CleanupStack::PopAndDestroy( cenrep );
+	if ( error != KErrNone )
+    	{
+        iMaxSizeKB = 0;
+    	}
+	if ( iMaxSizeKB < 0 )
+	    {
+	     iMaxSizeKB = 0;
+	    }
+    }
+
+// -----------------------------------------------------------------------------
+// CProfileToneHandler::CheckToneFileSizeL
+// -----------------------------------------------------------------------------
+//
+TInt CProfileToneHandler::CheckToneFileSizeL( const TDesC& aFile,
+                                              TInt aSizeLimitKB )
+    {
+    // Get file size
+    TInt size = 0;
+    TInt error = KErrNone;
+
+    TEntry entry;
+    if ( iFs.Entry( aFile, entry ) == KErrNone )
+        {
+        size = entry.iSize;        
+        }
+
+	// Check. NOTE: now if file size couldn't be determined, check fails.
+	aSizeLimitKB *= KKilo;
+	if ( aSizeLimitKB  &&  size > aSizeLimitKB )
+		{
+		error = KErrTooBig;
+		}
+
+    return error;
+    }
+
+
+//  End of File