eventsui/eventseditor/src/evtmgmtuiringtonecomponent.cpp
author Pat Downey <patd@symbian.org>
Wed, 01 Sep 2010 12:31:27 +0100
branchRCL_3
changeset 18 870918037e16
parent 0 522cd55cc3d7
permissions -rw-r--r--
Revert incorrect RCL_3 drop: Revision: 201033 Kit: 201035

/*
* Copyright (c) 2008 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:   'Set Assigntone' component for retrieving ringtone.
*
*/

#include <evtmgmteditorui.rsg>
#include <StringLoader.h>
#include <CFLDFileListContainer.h>  // Audio File List
#include <DRMHelper.h>              // DRM
#include <eikenv.h>
#include <aknlistquerydialog.h>
#include <pathinfo.h>
#include <driveinfo.h>
#include <f32file.h>
#include <NewFileServiceClient.h>   // Voice Recorder
#include <AiwGenericParam.h>    
#include <AknIconArray.h>       // Icon Array
#include <evteditor.mbg>
#include <avkon.mbg>
#include <AknsUtils.h>
#include <AknsSkinInstance.h>
#include <data_caging_path_literals.hrh>
#include <gulicon.h>            // Gul Icon
#include <eikapp.h>
#include <eikappui.h>
#include <CalendarDomainCRKeys.h>
#include <centralrepository.h>
#include <AknUtils.h>
#include <collate.h>

#include "evtmgmteditorui.hrh"
#include "evtmgmtuiringtonecomponent.h"
#include "evtdebug.h"
#include "evteditorconsts.h"

const TInt KSetToneGranularity = 2;

// ---------------------------------------------------------------------------
// CEvtEditor ::NewL()
// ---------------------------------------------------------------------------
//
CEvtMgmtUiRingtoneComponent* CEvtMgmtUiRingtoneComponent::NewL(const TPtrC aPrevRingtone)
    {
    CEvtMgmtUiRingtoneComponent * self = CEvtMgmtUiRingtoneComponent::NewLC(aPrevRingtone);
    CleanupStack::Pop(self);
    return self;
    }

// ---------------------------------------------------------------------------
// CEvtEditor ::NewLC()
// ---------------------------------------------------------------------------
//
CEvtMgmtUiRingtoneComponent* CEvtMgmtUiRingtoneComponent::NewLC(const TPtrC aPrevRingtone)
    {
    CEvtMgmtUiRingtoneComponent * self = new (ELeave) CEvtMgmtUiRingtoneComponent();
    CleanupStack::PushL(self);
    self->ConstructL( aPrevRingtone );
    return self;
    }

// ---------------------------------------------------------------------------
// CEvtMgmtUiDescComponent ::~CEvtMgmtUiDescComponent()
// ---------------------------------------------------------------------------
//
CEvtMgmtUiRingtoneComponent::~CEvtMgmtUiRingtoneComponent()
    {    
    delete iRingtone;
    iRingtone = NULL;
    
    if( iRecorderClient ) 
        {
        delete iRecorderClient;        
        iRecorderClient = NULL;
        }
        
    if( iSelectRingtoneDlg )
        {
        delete iSelectRingtoneDlg;        
        iSelectRingtoneDlg = NULL;
        }  
    }

// ---------------------------------------------------------------------------
// CEvtMgmtUiRingtoneComponent ::ConstructL()
// ---------------------------------------------------------------------------
//
void CEvtMgmtUiRingtoneComponent ::ConstructL( const TPtrC aPrevRingtone )
    {
    iRingtone = aPrevRingtone.AllocL();
    }

// ---------------------------------------------------------------------------
// CEvtMgmtUiRingtoneComponent ::CEvtMgmtUiRingtoneComponent()
// ---------------------------------------------------------------------------
//
CEvtMgmtUiRingtoneComponent::CEvtMgmtUiRingtoneComponent()
    {    
    }

// -----------------------------------------------------------------------------
// CEvtMgmtUiRingtoneComponent::Ringtone()
// It is used to retrieve the selected ringtone's absolute path.
// @ret absolute path of the selected ringtone
// -----------------------------------------------------------------------------
TPtrC CEvtMgmtUiRingtoneComponent::Ringtone() const
    {
    // if ringtone, returns ringtone else empty string
    if( iRingtone )
        return *iRingtone;
    else
        return KNullDesC();
    }

// -----------------------------------------------------------------------------
// CEvtMgmtUiRingtoneComponent::DefaultRingtoneL()
// It is used to retrieve the path of the Default Tone.
// @ret absolute path of the default ringtone
// -----------------------------------------------------------------------------
TPtrC CEvtMgmtUiRingtoneComponent::DefaultRingtoneL()
    {
    TFileName toneFileName;
    CRepository* centralRepository = CRepository::NewLC(KCRUidCalendar);
    User::LeaveIfError(centralRepository->Get(KCalendarSoundFile, toneFileName));
    CleanupStack::PopAndDestroy(centralRepository);
    if( iRingtone )
        {
        delete iRingtone;
        iRingtone = NULL;
        }
    iRingtone = toneFileName.AllocL();   
    
    // if ringtone, returns ringtone else empty string
    if( iRingtone )
        return *iRingtone;
    else
        return KNullDesC();
    }

// -----------------------------------------------------------------------------
// CEvtMgmtUiRingtoneComponent::DisplayAudioPopupDlgL()
// It is used to display 'Set tone' popup dialog and to retrieve ringtone.
// @ret error if there is any error
//      KErrNone if it is successful  
// -----------------------------------------------------------------------------
TInt CEvtMgmtUiRingtoneComponent::DisplayAudioTonePopupDlgL()
    {    
    TInt response = KErrNone;   
    
    //display 'set tone' popup dialog   
    TInt index = DisplayPopupDlgL();
   
    switch(index)
        {        
        case EEvtMgmtUiAssignedToneTone: // if 'select from exising' is selected
            {
            response = DisplayRingtoneSelectionDlgL();
            break;
            }
        case EvtMgmtUiAssignedToneRecordNew: //if 'record new' is selected
            {
            response = RecordNewToneL();
            break;
            }
        default:
            {
            response = KErrCancel;
            Debug(_L("DisplayAudioTonePopupDlgL panic"));
            break;
            }
        }    
     return response;
    }

// -----------------------------------------------------------------------------
// CEvtMgmtUiRingtoneComponent::DisplayRingtoneSelectionDlgL()
// t is used display  system's 'select tone' dialog.
// @ret error while displaying 'select tone' dialog and 
//      retrieving ringtone from it. 
//      KErrNone if it is successful
// -----------------------------------------------------------------------------
TInt CEvtMgmtUiRingtoneComponent::DisplayRingtoneSelectionDlgL()
    {
    TInt response = KErrNone;
    
    // Create instance of FileList using new FileList API
    if(!iSelectRingtoneDlg)
        iSelectRingtoneDlg = CFLDFileListContainer::NewL();

    iSelectRingtoneDlg->SetAutomatedType( CDRMHelper::EAutomatedTypeRingingTone );

    // Do not show videos, use new FileList API
    iSelectRingtoneDlg->AddExclusiveMediaTypeL( ECLFMediaTypeVideo );
    
    HBufC* strOff = StringLoader::LoadLC( R_EVTUI_RINGTONESELECT_OFF );
    
    iSelectRingtoneDlg->InsertEndNullItemL( *strOff );
    TFileName ringtone( *iRingtone );
    
    //launch selection dialog
    if( iSelectRingtoneDlg->LaunchL( ringtone ) ) //if ringtone is selected
        {        
        delete iRingtone;
        iRingtone = NULL;
        iRingtone = ringtone.AllocL();   
        }
    else // if dialog is cancelled
        response = KErrCancel;
    
    CleanupStack::PopAndDestroy(1 ); // strOff
    delete iSelectRingtoneDlg;
    iSelectRingtoneDlg = NULL;
    
    //return error code
    return response;
    }

// -----------------------------------------------------------------------------
// CEvtMgmtUiRingtoneComponent::DisplayPopupDlgL()
// It is used to display generic popup dialog.
// @ret index of item selected if OK is pressed
//       KErrCancel if Cancel is pressed 
// -----------------------------------------------------------------------------
TInt CEvtMgmtUiRingtoneComponent::DisplayPopupDlgL()
    {
    TInt index = 0;
    const TInt KToneIconIndex = 0;
    const TInt KRecordNewIconIndex = 1;
    const TInt KIconTextLength = 1;
    const TInt KAssignToneGranularity =2;   
    _LIT(KTab, "\t");  
    HBufC* dummy = NULL;
    
    //title text
    HBufC* title  = StringLoader::LoadLC( R_EVTUI_CREATENEW_FORM_ASSIGNTONEPOPUP_TITLE );
     
    //Tone
    dummy = StringLoader::LoadLC(R_EVTUI_CREATENEW_FORM_ASSIGNTONEPOPUPOPTIONS_TONE);
    HBufC* tone = HBufC::NewL( KIconTextLength + KTab().Length() + 
                       dummy->Length() + KTab().Length( )+ KTab().Length() );
    TPtr ptrDummy = tone->Des();
    ptrDummy.Num(KToneIconIndex);
    ptrDummy.Append(KTab);
    ptrDummy.Append(*dummy);
    ptrDummy.Append(KTab);
    ptrDummy.Append(KTab);
    CleanupStack::PopAndDestroy(dummy);
    CleanupStack::PushL(tone);
    
    // Record new
    dummy = StringLoader::LoadLC(R_EVTUI_CREATENEW_FORM_ASSIGNTONEPOPUPOPTIONS_RECORDNEW);
    HBufC* recordNew = HBufC::NewL( KIconTextLength + KTab().Length() + 
                      dummy->Length() + KTab().Length( )+ KTab().Length() );
    ptrDummy.Set( recordNew->Des() );
    ptrDummy.Num(KRecordNewIconIndex);
    ptrDummy.Append(KTab);
    ptrDummy.Append(*dummy);
    ptrDummy.Append(KTab);
    ptrDummy.Append(KTab);
    CleanupStack::PopAndDestroy(dummy);
    CleanupStack::PushL(recordNew);
    
    //array
    CDesCArrayFlat* array = new(ELeave)CDesCArrayFlat( KAssignToneGranularity );
    CleanupStack::PushL(array);
    array->AppendL(*tone);
    array->AppendL(*recordNew);
    
    //launch dialog
    CAknListQueryDialog* dlg = new( ELeave ) CAknListQueryDialog( &index );
    dlg->PrepareLC( R_EVTMGMTUI_LIST_QUERY );  
    UpdateIconsL( *dlg );
    dlg->SetItemTextArray( array ); 
    dlg->SetOwnershipType( ELbmOwnsItemArray );  
    dlg->QueryHeading()->SetTextL( *title );
    if ( !dlg->RunLD() )     // if dialog is cancelled  
       index = KErrCancel;   
    
    CleanupStack::Pop(array); //ownership was transferred to dialog
    
    CleanupStack::PopAndDestroy( 3 ); //recordNew, tone, title
    return index;
    }

// -----------------------------------------------------------------------------
// CEvtMgmtUiRingtoneComponent::RecordNewToneL()
// It is used to record new ringtone.
// @ret KErrNone if recording is succesful.
//      error code if it is failed.
// -----------------------------------------------------------------------------
TInt CEvtMgmtUiRingtoneComponent::RecordNewToneL()
    {
    TInt err = KErrNone;
    
    TFileName fileName;
    err = FileNameForRecordingL( fileName );
    if(err!=KErrNone)
        {
        Debug( _L("Error while generating filename for recording =%d"), err );
        return err;
        }
    
    Debug( _L("Recording filename = ") );
    Debug( fileName );
    
    RFs fs;
    User::LeaveIfError( fs.Connect() );
    CleanupClosePushL(fs);
    fs.ShareProtected(); // The file server session must be in this mode

    
    // Record Audio Clip    
    if(!iRecorderClient)
        iRecorderClient = NewFileServiceFactory::NewClientL();  
       
    //create empty audio file
    RFile file;
    file.Replace( fs, fileName, EFileShareAny|EFileWrite  );
    CleanupClosePushL(file);
    
 
    // launch recorder application to record tone.
    TBool response = EFalse;
    CAiwGenericParamList* params = CAiwGenericParamList::NewLC();
    TAiwVariant variant;
    variant.Set( _L("file" ) );
    TAiwGenericParam param( EGenericParamURL, variant );
    params->AppendL( param );
    TRAP(err, response = iRecorderClient->NewFileL( file, params, ENewFileServiceAudio ) );   
    Debug( _L( "Error while recording =%d, response =%d" ), err, response );
    CleanupStack::PopAndDestroy( 2 ); // params, file
    delete iRecorderClient;
    iRecorderClient = NULL;
   //if recording is successful, set ringtone.
   if( response && err == KErrNone)
       {
       delete iRingtone;
       iRingtone = NULL;
       iRingtone = fileName.AllocL();
       }
   
   //if recording is cancelled, set err to KErrCancel
   if( !response )
       err = KErrCancel;       
   
   //if there is error in recording or recording is cancelled, delete the file.
   if( err!=KErrNone )
       fs.Delete( fileName );
   
   CleanupStack::PopAndDestroy(); //fs
   
   return err;
   }

// -----------------------------------------------------------------------------
// CEvtMgmtUiRingtoneComponent::RecordNewToneL()
// It is used to generate filename for recording new file.
// @param[out] aFileName - it will contain generated file-name
// @ret KErrNone if recording is succesful.
//      error code if it is failed.
// -----------------------------------------------------------------------------
TInt CEvtMgmtUiRingtoneComponent:: FileNameForRecordingL( TDes& aFileName )
    { 
    PathInfo::GetFullPath(aFileName, EDriveC, PathInfo::ESoundsPath );
    
    HBufC* recStr = StringLoader::LoadLC( R_LOCEV_LIST_VOREC_CLIP_NAME );
    
    //Open sound directory
    RDir directory;
    TInt err = directory.Open(CEikonEnv::Static()->FsSession(), aFileName, KEntryAttNormal);       
    if( err!=KErrNone )
       {     
       return err;
       }   
    CleanupClosePushL(directory);
    
    //Retrieve files from directory
    TEntryArray fileList;    
    err = directory.Read(fileList);
    
    TInt maxValue = 0;
    
    if ( err == KErrNone || err == KErrEof )
       {
       err = KErrNone;
       //Check folder's files and find last recent audio file    
       for (TInt i = 0; i < fileList.Count(); ++i)
           {
           TEntry fileEntry = fileList[i];
           
           TCollationMethod cm = *Mem::CollationMethodByIndex( 0 ); // default collation method
           cm.iFlags |= TCollationMethod::EIgnoreNone;
           
           //Check that file is valid audiofile                
           if (!fileEntry.IsReadOnly() && 
               !fileEntry.IsHidden() &&
               !fileEntry.IsSystem() && 
               !fileEntry.IsDir() &&
               TDesC::EIsPrefix == fileEntry.iName.HasPrefixC(*recStr, 0, &cm) &&
               fileEntry.iName.Find(*recStr) != KErrNotFound)
               {
               //Find out running number
               TParse parser;
               parser.Set( fileEntry.iName, NULL, NULL );
               TFileName fileName = parser.Name();
               fileName.Delete(0,recStr->Length());
               fileName.Trim();

               //Convert digits from any digit format to european digit format. 
               AknTextUtils::ConvertDigitsTo( fileName, EDigitTypeWestern );
                               
               TInt multiplier = 1;
               TInt count = 0;
               for (TInt i = fileName.Length() - 1; i != -1;  --i)
                   {
                   TChar numberchar = fileName[i];
                   //Check if the character is digit
                   if( numberchar.IsDigit() )
                       {
                       TInt number = numberchar.GetNumericValue();
                       
                       count += number * multiplier;
                       multiplier = multiplier * 10;
                       }
                   else
                       {
                       break;
                       }
                   }
               
               //Save current number of audio files
               if (count > maxValue)
                   {
                   maxValue = count;
                   }
               }
           }
       }
    
    //Create a text containing the count to localize
    TFileName num;
    num.Zero();
    num.AppendNum(maxValue+1);

    //Converts between arabic-indic digits and european digits 
    //based on existing language setting.
    AknTextUtils::LanguageSpecificNumberConversion( num );
    
    //set recording filename
    aFileName.Append(*recStr);
    aFileName.Append(num);    
    aFileName.Append(KRecorderFileEnd);
    
    CleanupStack::PopAndDestroy(2); // dir, recStr
    
    return err;           
    }

// -----------------------------------------------------------------------------
// CEvtMgmtUiRingtoneComponent::UpdateIconsL
// It update icons
// -----------------------------------------------------------------------------
void CEvtMgmtUiRingtoneComponent::UpdateIconsL( CAknListQueryDialog& aDialog )
    {
    Debug(_L("start CEvtMgmtUiPlaceComponent::UpdateIconsL()"));
    
    CAknIconArray* icons = new( ELeave ) CAknIconArray( KSetToneGranularity );
    CleanupStack::PushL( icons );

    TFileName *iconFile = IconFileNameLC();

    AddIconL( *icons, 
              *iconFile,
              KAknsIIDQgnPropFmgrFileSound, 
              EMbmEvteditorQgn_prop_fmgr_file_sound, EMbmEvteditorQgn_prop_fmgr_file_sound_mask);
    
    AddIconL( *icons, 
             *iconFile,
             KAknsIIDQgnPropFmgrFileVoicerec, 
             EMbmEvteditorQgn_prop_fmgr_file_voicerec, EMbmEvteditorQgn_prop_fmgr_file_voicerec_mask);

    CleanupStack::PopAndDestroy(iconFile);

    //set new icons to array
    aDialog.SetIconArrayL( icons );  
    CleanupStack::Pop(icons);
    
    Debug(_L("end CEvtMgmtUiPlaceComponent::UpdateIconsL()"));
        
    }
    
// -----------------------------------------------------------------------------
// CEvtMgmtUiRingtoneComponent::AddIconL
// Append icon to icon array. CAknIconArray owns icons so it is 
// easier to it leave safely.
// @param aIcons icon array
// @param aIconFileWithPath icon file name with path
// @param aSkinID skin id of the icon
// @param aIconGraphicsIndex picture index
// @param aIconGraphicsMaskIndex mask index
// -----------------------------------------------------------------------------
void CEvtMgmtUiRingtoneComponent::AddIconL( CAknIconArray&  aIcons,
                                           const TDesC&    aIconFileWithPath,
                                           TAknsItemID     aSkinID,
                                           TInt            aIconGraphicsIndex,
                                           TInt            aIconGraphicsMaskIndex )
    {
    MAknsSkinInstance* skin = AknsUtils::SkinInstance();

    EVTUIDEBUG( "AknsUtils::SkinInstance" );
    
    CFbsBitmap* bitmap = NULL;
    CFbsBitmap* bitmapMask = NULL;
    TRAPD( err, AknsUtils::CreateIconL( skin,
                            aSkinID,
                            bitmap,
                            bitmapMask,
                            aIconFileWithPath,
                            aIconGraphicsIndex,
                            aIconGraphicsMaskIndex ) );

	
    EVTUIDEBUG1( "AknsUtils::CreateIconL - %d", err );
    if(err != KErrNone)
	    {
	    TRAP( err, AknIconUtils::CreateIconL( bitmap,
	                            bitmapMask,
	                            aIconFileWithPath,
	                            aIconGraphicsIndex,
	                            aIconGraphicsMaskIndex ) );
    	EVTUIDEBUG1( "AknIconUtils::CreateIconL - %d", err );
	    }
    User::LeaveIfError( err );
    
    CleanupStack::PushL( bitmap );
    CleanupStack::PushL( bitmapMask );
    
    CGulIcon* icon = CGulIcon::NewL( bitmap, bitmapMask );
    
    // Remove the Bitmap and the Bitmap Icon from the Clean up stack since 
    // the ownership is taken over by the icon
    CleanupStack::Pop( bitmapMask );
    CleanupStack::Pop( bitmap ); 
    
    CleanupStack::PushL( icon );
    aIcons.AppendL( icon );
    CleanupStack::Pop( icon ); // icon
    }

// -----------------------------------------------------------------------------
// CEvtMgmtUiRingtoneComponent::IconFileNameLC
// Gets Events Management UI icon file path and name. Ownership
// is transferred, item is left in the cleanup stack.
// @return TFileName* The full name of the Events UI icon file.
// -----------------------------------------------------------------------------
TFileName* CEvtMgmtUiRingtoneComponent::IconFileNameLC() const
    {
    TFileName* fileName = new(ELeave) TFileName;
    CleanupStack::PushL( fileName );
    
    TFileName* tmpName = new(ELeave) TFileName;
    CleanupStack::PushL( tmpName );
    
    tmpName->Append( KDC_BITMAP_DIR );
    tmpName->Append( KEvtMgmtUiIconFileName );

    CEikAppUi *appUi = ( CEikAppUi *)( CEikonEnv::Static()->AppUi());
    TFileName appDrive = appUi->Application()->AppFullName();
    
    TParse parse;
    User::LeaveIfError( parse.Set( appDrive, NULL, NULL ) );
    User::LeaveIfError( parse.Set( parse.Drive(), tmpName, NULL ) );
    
    fileName->Copy(parse.FullName());

    CleanupStack::PopAndDestroy( tmpName );

    return fileName;
    }  
//end of file