diff -r 000000000000 -r ca436256272f profilesapplication/Profiles/ProfileApp/SettingsViewSrc/CProfileToneHandler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/profilesapplication/Profiles/ProfileApp/SettingsViewSrc/CProfileToneHandler.cpp Thu Dec 17 08:45:58 2009 +0200 @@ -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 +#include // KProEngRingingToneMaxSize +#include // BaflUtils +#include // RApaLsSession +#include // CCoeEnv +#include // CAknInformationNote +#include // RConeResourceLoader +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 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 tempDataType; + tempDataType.Copy( dataType ); + + if( !ProfileMmfInfoUtility::IsMimeTypeSupportedL( tempDataType ) ) + { + // 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 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