--- /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