internetradio2.0/uisrc/irplsplaylist.cpp
changeset 0 09774dfdd46b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/internetradio2.0/uisrc/irplsplaylist.cpp	Mon Apr 19 14:01:53 2010 +0300
@@ -0,0 +1,423 @@
+/*
+* Copyright (c) 2007-2007 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:  Describes a single item in PLS playlist.
+*
+*/
+
+
+#include <f32file.h>
+
+#include "irplsplaylist.h"
+#include "irplsplaylistitem.h"
+#include "irdebug.h"
+
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// CIRPlsPlayList::CIRPlsPlayList
+// ---------------------------------------------------------------------------
+//
+CIRPlsPlayList::CIRPlsPlayList()
+    {
+    IRLOG_DEBUG( "CIRPlsPlayList::CIRPlsPlayList" );
+    }
+    
+// ---------------------------------------------------------------------------
+// CIRPlsPlayList::ConstructL
+// ---------------------------------------------------------------------------
+//
+void CIRPlsPlayList::ConstructL(RFile& aFileToParse)
+    {
+    IRLOG_DEBUG( "CIRPlsPlayList::ConstructL - Entering" );
+    ParseFileL(aFileToParse);
+    IRLOG_DEBUG( "CIRPlsPlayList::ConstructL - Exiting" );
+    }
+
+// ---------------------------------------------------------------------------
+// CIRPlsPlayList::NewL
+// ---------------------------------------------------------------------------
+//
+CIRPlsPlayList* CIRPlsPlayList::NewL(RFile& aFileToParse)
+    {
+    IRLOG_DEBUG( "CIRPlsPlayList::NewL - Entering" );
+    CIRPlsPlayList* self = CIRPlsPlayList::NewLC(aFileToParse);
+    CleanupStack::Pop( self );
+    IRLOG_DEBUG( "CIRPlsPlayList::NewL - Exiting" );
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// CIRPlsPlayList::NewLC
+// ---------------------------------------------------------------------------
+//
+CIRPlsPlayList* CIRPlsPlayList::NewLC(RFile& aFileToParse)
+    {
+    IRLOG_DEBUG( "CIRPlsPlayList::NewLC - Entering" );
+    CIRPlsPlayList* self = new( ELeave ) CIRPlsPlayList;
+    CleanupStack::PushL( self );
+    self->ConstructL(aFileToParse);
+    IRLOG_DEBUG( "CIRPlsPlayList::NewLC - Exiting" );
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// CIRPlsPlayList::~CIRPlsPlayList
+// ---------------------------------------------------------------------------
+//
+CIRPlsPlayList::~CIRPlsPlayList()
+    {
+    IRLOG_DEBUG( "CIRPlsPlayList::~CIRPlsPlayList - Entering" );
+    iItems.ResetAndDestroy();
+    iItems.Close();	
+    iIndexes.Close();
+    IRLOG_DEBUG( "CIRPlsPlayList::~CIRPlsPlayList - Exiting" );
+    }
+
+// ---------------------------------------------------------------------------
+// CIRPlsPlayList::AddItemAt
+// ---------------------------------------------------------------------------
+//
+void CIRPlsPlayList::AddItemAtL( TInt aIndex, CIRPlsPlayListItem* aItem )
+    {
+    IRLOG_DEBUG( "CIRPlsPlayList::AddItemAtL - Entering" );
+    __ASSERT_DEBUG( iItems.Count() == iIndexes.Count(), User::Panic(_L("InternetRadio"), KErrCorrupt));
+    
+    TInt foundIndex = iIndexes.Find(aIndex);
+    if (foundIndex >= 0)
+        {
+        iItems.Remove(foundIndex);
+        //delete item;
+        iIndexes.Remove(foundIndex);
+        }
+    else if (foundIndex != KErrNotFound)
+        {
+        User::LeaveIfError(foundIndex);
+        }
+    else
+        {
+        }
+    iIndexes.AppendL(aIndex);
+    TRAPD( err, iItems.AppendL(aItem) )
+    if (err)
+        {
+        iIndexes.Remove(iIndexes.Count()-1);
+        User::Leave(err);
+        }
+    IRLOG_DEBUG( "CIRPlsPlayList::AddItemAtL - Exiting" );
+    }
+
+// ---------------------------------------------------------------------------
+// CIRPlsPlayList::RemoveItemAt
+// ---------------------------------------------------------------------------
+//
+void CIRPlsPlayList::RemoveItemAt( TInt aIndex )
+    {
+    IRLOG_DEBUG( "CIRPlsPlayList::RemoveItemAt - Entering" );
+    __ASSERT_DEBUG( iItems.Count() == iIndexes.Count(), User::Panic(_L("InternetRadio"), KErrCorrupt));
+    
+    TInt foundIndex = iIndexes.Find(aIndex);
+    if (foundIndex >= 0)
+        {
+        iItems.Remove(foundIndex);
+        //delete item;
+        iIndexes.Remove(foundIndex);
+        }
+    IRLOG_DEBUG( "CIRPlsPlayList::RemoveItemAt - Exiting" );
+    }
+
+// ---------------------------------------------------------------------------
+// CIRPlsPlayList::ItemAt
+// ---------------------------------------------------------------------------
+//
+CIRPlsPlayListItem* CIRPlsPlayList::ItemAt( TInt aIndex ) const
+    {
+    IRLOG_DEBUG( "CIRPlsPlayList::ItemAt - Entering" );
+    __ASSERT_DEBUG( iItems.Count() == iIndexes.Count(), User::Panic(_L("InternetRadio"), KErrCorrupt));
+    
+    CIRPlsPlayListItem* retItem = NULL;
+    TInt foundIndex = iIndexes.Find(aIndex);
+    if (foundIndex >= 0)
+        {
+        retItem = iItems[foundIndex];
+        }
+    IRLOG_DEBUG( "CIRPlsPlayList::ItemAt - Exiting" );
+    return retItem;
+    }
+
+// ---------------------------------------------------------------------------
+// CIRPlsPlayList::ItemAt
+// ---------------------------------------------------------------------------
+//
+TInt CIRPlsPlayList::Count() const
+    {
+    IRLOG_DEBUG( "CIRPlsPlayList::Count - Entering" );
+    __ASSERT_DEBUG( iItems.Count() == iIndexes.Count(), User::Panic(_L("InternetRadio"), KErrCorrupt));
+    IRLOG_DEBUG( "CIRPlsPlayList::Count - Exiting" );
+    
+    return iItems.Count();
+    }
+
+// ---------------------------------------------------------------------------
+// CIRPlsPlayList::ParseFileL
+// ---------------------------------------------------------------------------
+//
+void CIRPlsPlayList::ParseFileL(RFile& aFileToParse)
+    {
+    IRLOG_DEBUG( "CIRPlsPlayList::ParseFileL - Entering" );
+    TBool firstLine(ETrue);
+	TBool done(EFalse);
+	TInt numberOfEntries(0);
+	HBufC8* lineBuf = NULL;
+	while ( !done )
+	    {
+	    TInt ret = KErrNone;
+	    ReadLineL( aFileToParse, lineBuf, &ret );
+	    if (ret == KErrEof)
+	        {
+	        // Last line is in the buffer.
+	        done = ETrue;
+	        }
+	    CleanupStack::PushL( lineBuf );
+	    TPtr8 line( lineBuf->Des() );
+	    
+	    if( firstLine )
+	        {
+	        _LIT8(KIRHeader, "[playlist]");
+	        if( line.Compare( KIRHeader ) )
+    	        {
+    	        User::Leave(KErrCorrupt);
+    	        }
+	        firstLine = EFalse;
+	        }
+	    else
+	        {
+    	    _LIT8(KIRFileLine, "File");
+    	    _LIT8(KIRTitleLine, "Title");
+    	    _LIT8(KIRLengthLine, "Length");
+    	    _LIT8(KIRNumberOfEntries, "NumberOfEntries");
+    	    TPtrC8 contentType;
+    	    if( line.Find( KIRFileLine ) == 0 )
+    	        {
+    	        contentType.Set( KIRFileLine );
+    	        }
+    	    else if( line.Find( KIRTitleLine ) == 0 )
+    	        {
+    	        contentType.Set( KIRTitleLine );
+    	        }
+    	    else if( line.Find( KIRLengthLine ) == 0 )
+    	        {
+    	        contentType.Set( KIRLengthLine );
+    	        }
+    	    else if( line.FindC( KIRNumberOfEntries ) == 0 )
+    	        {
+    	        contentType.Set( KIRNumberOfEntries );
+    	        }
+    	    else
+    	        {
+    	        contentType.Set( KNullDesC8 );
+    	        }
+    	    // If found parsable content.
+    	    if( contentType.Length() )
+    	        {
+    	        // Every line must have an "equals" sign.
+        	    _LIT8(KIREqualsSign, "=");
+        	    TInt equalsSignPos = line.Find( KIREqualsSign );
+                if (equalsSignPos == KErrNotFound)
+                    {
+                    // Sign was not found.
+                    User::Leave(KErrCorrupt);
+                    }
+                // Find the content index of certain content types.
+                TInt contentIndex(0);
+                if ( (!contentType.Compare( KIRFileLine )) || 
+                     (!contentType.Compare( KIRTitleLine )) ||
+                     (!contentType.Compare( KIRLengthLine )) )
+                    {
+            		TLex8 indexLex( line.Mid( contentType.Length(),
+            				 equalsSignPos-contentType.Length()) );
+            		indexLex.Val( contentIndex );
+            		if ( !contentIndex )
+                        {
+                        // Index couldn't be resolved.
+                        User::Leave(KErrCorrupt);
+                        }
+                    // To convert indexes "1.." of file to "0.." of array.
+                    --contentIndex;
+                    }
+        		TPtrC8 content( line.Mid( equalsSignPos+KIREqualsSign().Length() ) );
+        		if( !contentType.Compare( KIRFileLine ) )
+        		    {
+        		    HBufC* convertedContent = HBufC::NewLC(content.Length());
+            		convertedContent->Des().Copy(content);
+        		    CIRPlsPlayListItem* item = ItemAt(contentIndex);
+        		    if (item)
+        		        {
+        		        // Update existing item.
+            		    item->SetFileL(*convertedContent);
+        		        }
+        		    else
+        		        {
+        		        // Create new item.
+        		        item = CIRPlsPlayListItem::NewLC();	    
+            		    item->SetFileL( *convertedContent );
+            		    AddItemAtL( contentIndex, item );
+            		    CleanupStack::Pop( item );
+        		        }
+        		    CleanupStack::PopAndDestroy( convertedContent );
+        		    }
+        		else if( !contentType.Compare( KIRTitleLine ) )
+        		    {
+        		    HBufC* convertedContent = HBufC::NewLC(content.Length());
+            		convertedContent->Des().Copy(content);
+        		    CIRPlsPlayListItem* item = ItemAt(contentIndex);
+        		    if (item)
+        		        {
+        		        // Update existing item.
+            		    item->SetTitleL(*convertedContent);
+        		        }
+        		    else
+        		        {
+        		        // Create new item.
+        		        item = CIRPlsPlayListItem::NewLC();
+            		    item->SetTitleL( *convertedContent );
+            		    AddItemAtL( contentIndex, item );
+            		    CleanupStack::Pop( item );
+        		        }
+        		    CleanupStack::PopAndDestroy( convertedContent );
+        		    }
+        		else if( !contentType.Compare( KIRLengthLine ) )
+        		    {
+        		    TInt lengthVal(0);
+        		    TLex8 lengthLex( content );
+        		    lengthLex.Val( lengthVal ); 
+        		    CIRPlsPlayListItem* item = ItemAt(contentIndex);
+        		    if (item)
+        		        {
+        		        // Update existing item.
+            		    item->SetLength(lengthVal);
+        		        }
+        		    else
+        		        {
+        		        // Create new item.
+        		        item = CIRPlsPlayListItem::NewLC();
+            		    item->SetLength(lengthVal);
+            		    AddItemAtL( contentIndex, item );
+            		    CleanupStack::Pop( item );
+        		        }
+        		    }
+        		else if( !contentType.CompareC( KIRNumberOfEntries ) )
+        		    {
+        		    TLex8 numberLex( content );
+        		    numberLex.Val( numberOfEntries );
+        		    }
+        		else
+        		    {
+        		    }
+    	        }
+	        }
+	        
+	    CleanupStack::PopAndDestroy(lineBuf);
+	    }
+
+    if (Count() != numberOfEntries)
+        {
+        User::Leave(KErrCorrupt);
+        }
+    IRLOG_DEBUG( "CIRPlsPlayList::ParseFileL - Exiting" );
+    }
+
+// ---------------------------------------------------------------------------
+// CIRPlsPlayList::ReadLineL
+// ---------------------------------------------------------------------------
+//	
+void CIRPlsPlayList::ReadLineL( RFile& aFile, HBufC8*& aLineBuf, TInt *aError ) const
+    {
+    IRLOG_DEBUG( "CIRPlsPlayList::ReadLineL - Entering" );
+    *aError = KErrNone;
+    TInt filePos(0);
+    User::LeaveIfError( aFile.Seek( ESeekCurrent, filePos ) );
+    TInt endLine( KErrNotFound );
+    TInt readAmount( 0 );
+    const TInt KIRBytesToRead = 64;
+    // Find next line end mark index.
+    while ( endLine == KErrNotFound )
+        {
+        // Increase read amount if end of line hasn't been yet found.
+        readAmount = readAmount + KIRBytesToRead;
+       	HBufC8* nextBuf = HBufC8::NewLC( readAmount );
+        TPtr8 next( nextBuf->Des() );
+        User::LeaveIfError( aFile.Seek( ESeekStart, filePos ) );
+        User::LeaveIfError( aFile.Read( next, readAmount ) );
+        // Locate nearest LF and CR.
+        TInt lfEnd = next.Locate(EKeyLineFeed);
+        TInt crEnd = next.Locate(EKeyEnter);
+        if ((lfEnd != KErrNotFound) || (crEnd != KErrNotFound))
+            {
+            // Either CR or LF was found.
+	        if( ((lfEnd != KErrNotFound) && (crEnd != KErrNotFound) && (lfEnd < crEnd)) || 
+                (crEnd == KErrNotFound) )
+                {
+                // LF is nearer.
+                if (lfEnd)
+                    {
+                    // Mark end line position as the position of LF.
+                    endLine = lfEnd;
+                    }
+                else
+                    {
+                    // LF is at the begining of the line.
+                    // Skip it and read file again but not increase read amount.
+                    ++filePos;
+                    readAmount = readAmount - KIRBytesToRead;
+                    }
+                }
+            else
+                {
+                // CR is nearer.
+                if (crEnd)
+                    {
+                    // Mark end line position as the position of CR.
+                    endLine = crEnd;
+                    }
+                else
+                    {
+                    // CR is at the begining of the line.
+                    // Skip it and read file again but not increase read amount.
+                    ++filePos;
+                    readAmount = readAmount - KIRBytesToRead;
+                    }
+                }
+            }
+        else
+            {
+            // No CR or LF was found.
+            // Check are we in the end of the file.
+            if (next.Length() < readAmount)
+                {
+                // Reached the end of file.
+                endLine = next.Length();
+                *aError = KErrEof;
+                }
+            }
+        CleanupStack::PopAndDestroy(nextBuf);
+        }
+    // Read the line to buf.
+    aLineBuf = HBufC8::NewLC( endLine );
+    TPtr8 line( aLineBuf->Des() );
+    User::LeaveIfError( aFile.Seek( ESeekStart, filePos ) );
+    User::LeaveIfError( aFile.Read( line, endLine ) );
+    CleanupStack::Pop( aLineBuf );
+    IRLOG_DEBUG( "CIRPlsPlayList::ReadLineL - Exiting" );
+    }