--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mmappcomponents/playlistengine/src/mpxplaylistengine.cpp Thu Dec 17 08:55:47 2009 +0200
@@ -0,0 +1,832 @@
+/*
+* Copyright (c) 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: playlist engine
+*
+* CMPXPlaylistEngine contains a CMPXPlaylistPluginHandler and a task queue.
+* CMPXPlaylistEngine uses CMPXPlaylistPluginHandler to select an appropriate
+* playlist plugin to handle the client's requests. It's also used for querying
+* about the currently loaded playlist plugin.
+*
+* The task queue is used to manage async requests submitted by the client.
+* When an InternalizePlaylistL or ExternalizePlaylistL request is received,
+* it's added to the task queue. When a task in the queue is ready for
+* execution, ExecuteTask is called. To process the task, CMPXPlaylistEngine
+* will select an appropriate plugin; once one is found, the request is
+* handed over to the plugin and CMPXPlaylistEngine becomes active. Before
+* the plugin completes the request, CMPXPlaylistEngine is notified of the
+* results through MMPXPlaylistPluginObserver interface; CMPXPlaylistEngine
+* passes the results to its client through MMPXPlaylistEngineObserver
+* interface. Once CMPXPlaylistEngine's client completes the handling of the
+* results, plugin completes the request and CMPXPlaylistEngine::RunL
+* is called to complete one task processing cycle. CMPXPlaylistEngine is
+* ready to process the next task if any at the completion of RunL.
+*
+* DESIGN DECISION:
+* Only one task queue is used instead of one per plugin because this is
+* running on the client thread. No processing time gained for having
+* separate task queues.
+*
+*
+*/
+
+#include <s32mem.h>
+#include <bamdesca.h>
+#include <badesca.h>
+#include <bautils.h>
+#include <uri16.h>
+#include <apmrec.h>
+#include <syslangutil.h>
+#include <languages.hrh>
+#include <data_caging_path_literals.hrh>
+#include <mpxplaylisttopcharacterset.rsg>
+#include <mpxlog.h>
+#include <mpxtaskqueue.h>
+#include <mpxmedia.h>
+#include <mpxmediaarray.h>
+#include <mpxmediageneraldefs.h>
+#include <mpxmediacontainerdefs.h>
+#include "mpxplaylistenginedefs.hrh"
+#include "mpxplaylistplugin.h"
+#include "mpxplaylistengine.h"
+#include "mpxplaylistrecognizer.h"
+
+// ============================ CONSTANTS =====================================
+const TInt KMPXBufExpandSize = 0x40;
+const TInt KMPXArrayGranularity = 12;
+_LIT( KMPXPlaylistEnginePanic, "CMPXPlaylistEngine");
+_LIT(KMPXPlaylistCharacterSetRscFile, "mpxplaylisttopcharacterset.rsc");
+_LIT( KMPXPlaylistExtension, ".m3u" );
+
+// ============================ MEMBER FUNCTIONS ==============================
+// ----------------------------------------------------------------------------
+// Constructor.
+// ----------------------------------------------------------------------------
+//
+CMPXPlaylistEngine::CMPXPlaylistEngine(
+ MMPXPlaylistEngineObserver& aObserver)
+: CActive(EPriorityStandard),
+ iObserver(aObserver)
+ {
+ CActiveScheduler::Add(this);
+ }
+
+// ----------------------------------------------------------------------------
+// 2nd phase constructor.
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaylistEngine::ConstructL()
+ {
+ User::LeaveIfError(iFs.Connect());
+ iCharacterSet = CCnvCharacterSetConverter::CreateArrayOfCharacterSetsAvailableL(iFs);
+ iTopCharacterSet =
+ new (ELeave)CArrayFixFlat<CCnvCharacterSetConverter::SCharacterSet>(KMPXArrayGranularity);
+ GenerateTopCharacterSetsL();
+
+ iTaskQueue = CMPXActiveTaskQueue::NewL();
+ iPluginHandler = CMPXPlaylistPluginHandler::NewL(
+ *this, *this, iFs, *iTopCharacterSet, *iCharacterSet);
+ }
+
+// ----------------------------------------------------------------------------
+// Two-phased constructor.
+// ----------------------------------------------------------------------------
+//
+EXPORT_C CMPXPlaylistEngine* CMPXPlaylistEngine::NewL(
+ MMPXPlaylistEngineObserver& aObserver)
+ {
+ CMPXPlaylistEngine* self=new(ELeave)CMPXPlaylistEngine(aObserver);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+// ----------------------------------------------------------------------------
+// Destructor.
+// ----------------------------------------------------------------------------
+//
+EXPORT_C CMPXPlaylistEngine::~CMPXPlaylistEngine()
+ {
+ Cancel();
+ Cleanup();
+
+ iFs.Close();
+ delete iTaskQueue;
+ delete iPluginHandler;
+ delete iCharacterSet;
+ delete iTopCharacterSet;
+ iRscFile.Close();
+ }
+
+// =========================== EXTERNAL FUNCTIONS =============================
+// ----------------------------------------------------------------------------
+// Return a handle to playlist plugin handler
+// ----------------------------------------------------------------------------
+EXPORT_C CMPXPlaylistPluginHandler& CMPXPlaylistEngine::PlaylistPluginHandler()
+ {
+ ASSERT( iPluginHandler );
+ return *iPluginHandler;
+ }
+
+// ----------------------------------------------------------------------------
+// Determines whether the given media is a playlist
+// Currently, Music Player only supports m3u playlist.
+// ----------------------------------------------------------------------------
+//
+EXPORT_C TBool CMPXPlaylistEngine::IsPlaylistL( const TDesC& aUri )
+ {
+ // Check if the file extension is ".m3u".
+ TBool isPlaylist = EFalse;
+ TParsePtrC parse( aUri );
+ if ( !parse.Ext().CompareF( KMPXPlaylistExtension ) )
+ {
+ isPlaylist = ETrue;
+ }
+
+ return isPlaylist;
+ }
+
+// ----------------------------------------------------------------------------
+// Internalize a playlist (async)
+//
+// Add the request to the task queue
+// ----------------------------------------------------------------------------
+EXPORT_C void CMPXPlaylistEngine::InternalizePlaylistL(const TDesC& aPlaylistUri)
+ {
+ MPX_DEBUG1("CMPXPlaylistEngine::InternalizePlaylistL");
+
+ //
+ // leave if the given file does not exist
+ //
+ if (!BaflUtils::FileExists(iFs, aPlaylistUri))
+ {
+ User::Leave( KErrNotFound );
+ }
+
+ //
+ // externalize parameters
+ //
+ CBufBase* taskParam = CBufFlat::NewL( KMPXBufExpandSize );
+ CleanupStack::PushL( taskParam );
+ taskParam->ResizeL( KMPXBufExpandSize );
+
+ RBufWriteStream writeStream( *taskParam );
+ CleanupClosePushL( writeStream );
+
+ // externalize playlist URI
+ writeStream.WriteInt32L( aPlaylistUri.Length() );
+ writeStream << aPlaylistUri;
+
+ writeStream.CommitL();
+ taskParam->Compress();
+
+ //
+ // add request to the task queue
+ //
+ iTaskQueue->AddTaskL( EInternalizePlaylist,
+ NULL, // callback when task completed
+ this, // task queue observer
+ 0, // Integer parameter, not used
+ taskParam ); // task queue assumes ownership of taskParam
+
+ CleanupStack::PopAndDestroy( &writeStream );
+ CleanupStack::Pop( taskParam ); // taskParam
+ }
+
+// ----------------------------------------------------------------------------
+// Internalize a playlist (async)
+// ----------------------------------------------------------------------------
+EXPORT_C void CMPXPlaylistEngine::InternalizePlaylistL(const RFile& aPlaylistFileHandle)
+ {
+ MPX_DEBUG1("CMPXPlaylistEngine::InternalizePlaylistL");
+
+ if ( !aPlaylistFileHandle.SubSessionHandle() )
+ {
+ User::Leave(KErrArgument);
+ }
+
+ TFileName fullName;
+ aPlaylistFileHandle.FullName( fullName );
+
+ InternalizePlaylistL( fullName );
+ }
+
+// ----------------------------------------------------------------------------
+// Externalize a playlist (async)
+//
+// Add the request to the task queue
+// ----------------------------------------------------------------------------
+EXPORT_C void CMPXPlaylistEngine::ExternalizePlaylistL(
+ const CMPXMedia& aPlaylist,
+ const TDesC& aFilePath)
+ {
+ MPX_DEBUG1("CMPXPlaylistEngine::ExternalizePlaylistL");
+
+ //
+ // leave if the given playlist doesn't contain the following attributes
+ //
+ if (!aPlaylist.IsSupported(KMPXMediaGeneralTitle) ||
+ !aPlaylist.IsSupported(KMPXMediaGeneralType) ||
+ !aPlaylist.IsSupported(KMPXMediaGeneralCategory) ||
+ !aPlaylist.IsSupported(KMPXMediaArrayContents) ||
+ !aPlaylist.IsSupported(KMPXMediaArrayCount))
+ {
+ User::Leave( KErrArgument );
+ }
+
+ //
+ // leave if the given media isn't a playlist (i.e. type must be EMPXItem and category
+ // must be EMPXPlaylist
+ //
+ TMPXGeneralType mediaType =
+ aPlaylist.ValueTObjectL<TMPXGeneralType>(KMPXMediaGeneralType);
+
+ TMPXGeneralCategory mediaCategory =
+ aPlaylist.ValueTObjectL<TMPXGeneralCategory>(KMPXMediaGeneralCategory);
+
+ if ( mediaType != EMPXItem ||
+ mediaCategory != EMPXPlaylist )
+ {
+ User::Leave( KErrArgument );
+ }
+
+ //
+ // leave if the given file path does not exist
+ //
+ if (!BaflUtils::PathExists(iFs, aFilePath))
+ {
+ User::Leave( KErrPathNotFound );
+ }
+
+ // check if a plugin has been selected. the client
+ // is required to select a plugin before issuing
+ // this request
+ if ( !iPluginHandler->PluginFound() )
+ {
+ User::Leave( KErrNotFound );
+ }
+
+ //
+ // externalize parameters
+ //
+ CBufBase* taskParam = CBufFlat::NewL( KMPXBufExpandSize );
+ CleanupStack::PushL( taskParam );
+ taskParam->ResizeL( KMPXBufExpandSize );
+
+ RBufWriteStream writeStream( *taskParam );
+ CleanupClosePushL( writeStream );
+
+ // externalize playlist
+ writeStream << aPlaylist;
+
+ // externalize file path
+ writeStream.WriteInt32L( aFilePath.Length() );
+ writeStream << aFilePath;
+
+ // externalize plugin Uid
+ writeStream.WriteInt32L( iPluginHandler->PluginUid().iUid );
+
+ writeStream.CommitL();
+ taskParam->Compress();
+
+ //
+ // add request to the task queue
+ //
+ CMPXMedia* playlist = CMPXMedia::NewL(aPlaylist);
+ CleanupStack::PushL(playlist);
+
+ iTaskQueue->AddTaskL( EExternalizePlaylist,
+ NULL, // callback when task completed
+ this, // task queue observer
+ 0, // Integer parameter, not used
+ taskParam, // task queue assumes ownership
+ NULL,
+ playlist ); // keep media alive. ownership transferred
+
+ CleanupStack::Pop( playlist );
+ CleanupStack::PopAndDestroy( &writeStream );
+ CleanupStack::Pop( taskParam ); // taskParam
+ }
+
+// ----------------------------------------------------------------------------
+// Cancel Requests
+// ----------------------------------------------------------------------------
+EXPORT_C void CMPXPlaylistEngine::CancelRequests()
+ {
+ MPX_DEBUG1("CMPXPlaylistEngine::CancelRequests");
+ Cancel();
+ iTaskQueue->CancelRequests();
+ }
+
+// =========================== CALLBACK FUNCTIONS =============================
+// ----------------------------------------------------------------------------
+// Handles plugin callback for InternalizePlaylistL request
+// ----------------------------------------------------------------------------
+void CMPXPlaylistEngine::HandlePlaylistL(
+ CMPXMedia* aPlaylist,
+ const TInt aError,
+ const TBool aCompleted)
+ {
+ MPX_DEBUG1("CMPXPlaylistEngine::HandlePlaylistL");
+
+ // notify playlist engine observer
+ iObserver.HandlePlaylistL( aPlaylist, aError, aCompleted );
+ }
+
+// ----------------------------------------------------------------------------
+// Handle plugin callback for ExternalizePlaylistL request
+// ----------------------------------------------------------------------------
+void CMPXPlaylistEngine::HandlePlaylistL(
+ const TDesC& aPlaylistUri,
+ const TInt aError)
+ {
+ MPX_DEBUG1("CMPXPlaylistEngine::HandlePlaylistL");
+
+ // notify playlist engine observer
+ iObserver.HandlePlaylistL( aPlaylistUri, aError );
+ }
+
+// =========================== INTERNAL FUNCTIONS =============================
+// ----------------------------------------------------------------------------
+// Handles request completion event
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaylistEngine::RunL()
+ {
+ MPX_DEBUG2("CMPXPlaylistEngine::RunL - status %d", iStatus.Int());
+
+ // clean up data set during processing of the current task
+ Cleanup();
+
+ // we are done with the current request and ready for the next one if there is
+ // any
+ iTaskQueue->CompleteTask();
+ }
+
+// ----------------------------------------------------------------------------
+// Cancellation of an outstanding request.
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaylistEngine::DoCancel()
+ {
+ if ( iPluginHandler->PluginFound() )
+ {
+ iPluginHandler->Plugin()->Cancel();
+ }
+ Cleanup();
+ iTaskQueue->CompleteTask();
+ }
+
+// ----------------------------------------------------------------------------
+// Execute an async task
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaylistEngine::ExecuteTask(
+ TInt aTask,
+ TInt /*aParamData*/,
+ TAny* /*aPtrData*/,
+ const CBufBase& aBuf,
+ TAny* /*aCallback*/,
+ CBase* /*aCObject1*/,
+ CBase* /*aCObject2*/)
+ {
+ TRAPD(err, ExecuteTaskL(aTask, aBuf));
+ if (err != KErrNone)
+ {
+ HandleExecuteTaskError(aTask, err);
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// CMPXPlaylistEngine::HandleTaskError
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaylistEngine::HandleTaskError(
+ TInt /* aTask */,
+ TAny* /*aPtrData*/,
+ TAny* /*aCallback*/,
+ TInt /* aError */)
+ {
+ // do nothing
+ }
+
+// ----------------------------------------------------------------------------
+// CMPXPlaylistEngine::HandlePluginHandlerEvent
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaylistEngine::HandlePluginHandlerEvent(
+ TPluginHandlerEvents /* aEvent */,
+ const TUid& /* aPluginUid */,
+ TBool /* aLoaded */,
+ TInt /* aData */)
+ {
+ // Playlist plugins are stateless and they are resolved for every call.
+ // There is no need to cancel the existing queued requests in case the
+ // plugin is updated as the new version of the plugin is expected to handle
+ // these calls the same as the previous version did.
+ //
+ // In case the plugin is removed it is expected that all queued ResolvePluginL
+ // calls will leave with KErrNotSupported, which will be sent to the caller.
+ }
+
+// ----------------------------------------------------------------------------
+// Execute an async task. Leaves when an error is encountered.
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaylistEngine::ExecuteTaskL(TInt aTask, const CBufBase& aBuf)
+ {
+ __ASSERT_ALWAYS( !IsActive(), User::Panic(KMPXPlaylistEnginePanic, KErrInUse) );
+
+ RBufReadStream readStream( aBuf );
+ CleanupClosePushL( readStream );
+
+ switch( aTask )
+ {
+ case EInternalizePlaylist:
+ {
+ // internalize playlist parameter
+ iPlaylistUri = HBufC::NewL( readStream, readStream.ReadInt32L() );
+
+ // automatically select a plugin that is capable of handling
+ // the specified media file. SelectPlaylistPluginL leaves
+ // with KErrNotSupported when an appropriate plugin cannot
+ // be found
+ iPluginHandler->SelectPlaylistPluginL( *iPlaylistUri, KNullDesC8 );
+
+ // an appropriate plugin is found, issue the request to the
+ // selected plugin
+ iPluginHandler->Plugin()->InternalizePlaylistL( iStatus, *iPlaylistUri );
+ }
+ break;
+
+ case EExternalizePlaylist:
+ {
+ // internalize playlist
+ iPlaylist = CMPXMedia::NewL();
+ readStream >> *iPlaylist;
+
+ // internalize file path
+ iFilePath = HBufC::NewL( readStream, readStream.ReadInt32L() );
+
+ // internalize plugin Uid
+ TUid pluginUid = TUid::Uid( readStream.ReadInt32L() );
+
+ //
+ // select the specified plugin. When the specified plugin
+ // cannot be found, SelectPlaylistPluginL will leave with
+ // KErrNotSupported error code.
+ //
+ // Possible scenario:
+ // The specified plugin is available when the client made
+ // the selection before issuing the request, but the plugin
+ // has since been uninstalled when we are ready to process
+ // this request.
+ //
+ iPluginHandler->SelectPlaylistPluginL( pluginUid );
+
+ // found the specified plugin, issue the request
+ iPluginHandler->Plugin()->ExternalizePlaylistL(
+ iStatus, *iPlaylist, *iFilePath );
+ }
+ break;
+
+ //
+ // command not supported
+ //
+ default:
+ {
+ ASSERT(0);
+ break;
+ }
+ }
+
+ CleanupStack::PopAndDestroy( &readStream ); // readStream
+
+ SetActive();
+ }
+
+// ----------------------------------------------------------------------------
+// Handles a leave occurring in the request completion event handler ExecuteTaskL
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaylistEngine::HandleExecuteTaskError(TInt aTask, TInt aError)
+ {
+ TRAP_IGNORE(HandleExecuteTaskErrorL(aTask, aError));
+
+ // clean up data set during processing of the current task
+ Cleanup();
+
+ // although an error has occured while processing the current task, we are
+ // done with the current request and ready for the next one if there is
+ // any
+ iTaskQueue->CompleteTask();
+ }
+
+// ----------------------------------------------------------------------------
+// Handles a leave occurring in the request completion event handler ExecuteTaskL
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaylistEngine::HandleExecuteTaskErrorL(TInt aTask, TInt aError)
+ {
+ MPX_DEBUG3("CMPXPlaylistEngine::HandleExecuteTaskErrorL(task %d, error %d)", aTask, aError);
+
+ //
+ // notify client
+ //
+ switch (aTask)
+ {
+ case EInternalizePlaylist:
+ {
+ iObserver.HandlePlaylistL( NULL, aError, ETrue );
+ }
+ break;
+
+ case EExternalizePlaylist:
+ {
+ const TDesC& playlist =
+ iPlaylist? iPlaylist->ValueText(KMPXMediaGeneralTitle) : KNullDesC;
+
+ iObserver.HandlePlaylistL( playlist, aError );
+ }
+ break;
+
+ default:
+ {
+ ASSERT(0);
+ break;
+ }
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// cleanup
+// ----------------------------------------------------------------------------
+//
+void CMPXPlaylistEngine::Cleanup()
+ {
+ delete iPlaylistUri;
+ iPlaylistUri = NULL;
+
+ delete iFilePath;
+ iFilePath = NULL;
+
+ delete iPlaylist;
+ iPlaylist = NULL;
+ }
+
+// -----------------------------------------------------------------------------
+// CMPXPlaylistEngine::GenerateTopCharacterSets()
+// -----------------------------------------------------------------------------
+//
+void CMPXPlaylistEngine::GenerateTopCharacterSetsL()
+ {
+ CArrayFixFlat<TInt>* installedLanguages = NULL;
+ SysLangUtil::GetInstalledLanguages(installedLanguages);
+ CleanupStack::PushL(installedLanguages);
+
+
+ TParse* fp = new(ELeave) TParse();
+ fp->Set(KMPXPlaylistCharacterSetRscFile, &KDC_RESOURCE_FILES_DIR, NULL);
+ CleanupStack::PushL(fp);
+
+ TFileName resourceFile = fp->FullName();
+ User::LeaveIfError( MPXUser::CompleteWithDllPath( resourceFile ) );
+
+ // Open the resource file
+ TRAPD(err, iRscFile.OpenL(iFs, resourceFile));
+ // if there is no resource file, then there is no top character set list
+ if (err)
+ {
+ CleanupStack::PopAndDestroy(2, installedLanguages);
+ return;
+ }
+
+ for (TInt i=0; i < installedLanguages->Count(); i++)
+ {
+ SelectCharacterSetsForLanguageL(installedLanguages->At(i));
+ }
+ iTopCharacterSet->Compress();
+ installedLanguages->Reset();
+ CleanupStack::PopAndDestroy(2, installedLanguages);
+ iRscFile.Close();
+ }
+
+// -----------------------------------------------------------------------------
+// CMetaDataParser::SelectCharacterSetsForLanguage()
+// -----------------------------------------------------------------------------
+//
+void CMPXPlaylistEngine::SelectCharacterSetsForLanguageL(TInt aLanguage)
+ {
+ switch ( aLanguage )
+ {
+ case ELangEnglish:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_ENGLISH_CHAR_SET);
+ break;
+ case ELangFrench:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_FRENCH_CHAR_SET);
+ break;
+ case ELangGerman:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_GERMAN_CHAR_SET);
+ break;
+ case ELangTurkish:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_TURKISH_CHAR_SET);
+ break;
+ case ELangFinnish:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_FINNISH_CHAR_SET);
+ break;
+ case ELangSwedish:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_SWEDISH_CHAR_SET);
+ break;
+ case ELangRussian:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_RUSSIAN_CHAR_SET);
+ break;
+ case ELangArabic:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_ARABIC_CHAR_SET);
+ break;
+ case ELangHebrew:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_HEBREW_CHAR_SET);
+ break;
+ case ELangFarsi:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_FARSI_CHAR_SET);
+ break;
+ case ELangItalian:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_ITALIAN_CHAR_SET);
+ break;
+ case ELangPolish:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_POLISH_CHAR_SET);
+ break;
+ case ELangHungarian:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_HUNGARIAN_CHAR_SET);
+ break;
+ case ELangSpanish:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_SPANISH_CHAR_SET);
+ break;
+ case ELangDutch:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_DUTCH_CHAR_SET);
+ break;
+ case ELangPortuguese:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_PORTUGUESE_CHAR_SET);
+ break;
+ case ELangAmerican:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_ENGLISH_CHAR_SET);
+ break;
+ case ELangCanadianFrench:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_FRENCH_CHAR_SET);
+ break;
+ case ELangBrazilianPortuguese:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_PORTUGUESE_CHAR_SET);
+ break;
+ case ELangLatinAmericanSpanish:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_SPANISH_CHAR_SET);
+ break;
+ case ELangLatvian:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_LATVIAN_CHAR_SET);
+ break;
+ case ELangGreek:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_GREEK_CHAR_SET);
+ break;
+ case ELangEstonian:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_ESTONIAN_CHAR_SET);
+ break;
+ case ELangLithuanian:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_LITHUANIAN_CHAR_SET);
+ break;
+ case ELangRomanian:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_ROMANIAN_CHAR_SET);
+ break;
+ case ELangUkrainian:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_UKRAINIAN_CHAR_SET);
+ break;
+ case ELangBulgarian:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_BULGARIAN_CHAR_SET);
+ break;
+ case ELangCroatian:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_CROATIAN_CHAR_SET);
+ break;
+ case ELangSerbian:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_SERBIAN_CHAR_SET);
+ break;
+ case ELangIndonesian:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_INDONESIAN_CHAR_SET);
+ break;
+ case ELangMalay:
+ case ELangTagalog:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_MALAY_CHAR_SET);
+ break;
+ case ELangIcelandic:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_ICELANDIC_CHAR_SET);
+ break;
+ case ELangDanish:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_DANISH_CHAR_SET);
+ break;
+ case ELangNorwegian:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_NORWEGIAN_CHAR_SET);
+ break;
+ case ELangHindi:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_INDIAN_CHAR_SET);
+ break;
+ case ELangUrdu:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_URDU_CHAR_SET);
+ break;
+ case ELangCzech:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_CZECH_CHAR_SET);
+ break;
+ case ELangSlovak:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_SLOVAK_CHAR_SET);
+ break;
+ case ELangSlovenian:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_SLOVENIAN_CHAR_SET);
+ break;
+ case ELangTaiwanChinese:
+ case ELangHongKongChinese:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_TAIWAN_HK_CHINESE_CHAR_SET);
+ break;
+ case ELangPrcChinese:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_CHINESE_CHAR_SET);
+ break;
+ case ELangEnglish_Taiwan:
+ case ELangEnglish_Prc:
+ case ELangEnglish_Japan:
+ case ELangEnglish_Thailand:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_ENGLISH_CHAR_SET);
+ break;
+ case ELangJapanese:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_JAPANESE_CHAR_SET);
+ break;
+ case ELangThai:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_THAI_CHAR_SET);
+ break;
+ case ELangVietnamese:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_VIETNAMESE_CHAR_SET);
+ break;
+ case ELangMalay_Apac:
+ ReadCharacterSetResourceL(R_MPX_PLAYLIST_MALAY_CHAR_SET);
+ break;
+ default:
+ break;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CMPXPlaylistEngine::ReadCharacterSetResourceL()
+// -----------------------------------------------------------------------------
+//
+void CMPXPlaylistEngine::ReadCharacterSetResourceL(TInt aResourceId)
+ {
+ TResourceReader rscReader; // Resource reader
+ HBufC8* rscBuf; // Buffer where resource is read
+
+ rscBuf = iRscFile.AllocReadL(aResourceId);
+ rscReader.SetBuffer(rscBuf);
+ CleanupStack::PushL(rscBuf);
+
+ TUint characterSetElementId;
+ TInt numCharacterSetElements = rscReader.ReadInt16();
+ TUint elemId;
+ CCnvCharacterSetConverter::SCharacterSet elem;
+
+ for (TInt i = 0; i < numCharacterSetElements; i++)
+ {
+ characterSetElementId = rscReader.ReadInt32();
+ for (TInt j = 0; j < iCharacterSet->Count(); j++ )
+ {
+ elem = iCharacterSet->At(j);
+ elemId = elem.Identifier();
+ if ( elemId == characterSetElementId && !IsInTopCharacterSet(characterSetElementId) )
+ {
+ iTopCharacterSet->AppendL(elem);
+ }
+ }
+ }
+
+ CleanupStack::PopAndDestroy(rscBuf);
+ }
+
+// -----------------------------------------------------------------------------
+// CMPXPlaylistEngine::IsInTopCharacterSet()
+// -----------------------------------------------------------------------------
+//
+TBool CMPXPlaylistEngine::IsInTopCharacterSet(TUint aCharacterSetId)
+ {
+ for (TInt i = 0; i < iTopCharacterSet->Count(); i++)
+ {
+ if ( iTopCharacterSet->At(i).Identifier() == aCharacterSetId )
+ {
+ return ETrue;
+ }
+ }
+ return EFalse;
+ }
+
+// End of file