--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/internetradio2.0/streamsourcesrc/irstreamsource.cpp Mon Apr 19 14:01:53 2010 +0300
@@ -0,0 +1,425 @@
+/*
+* Copyright (c) 2006-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: Stream source main class implementation
+*
+*/
+
+
+#include <e32property.h>
+#include "irpubsubkeys.h"
+
+#include "irdebug.h"
+#include "irnetworkcontroller.h"
+#include "irstreamsource.h"
+#include "irstreamsourceerrors.h"
+#include "irstreamsourceobserver.h"
+#include "irstationconnection.h"
+
+
+// Constants
+const TInt KIRSCConnectionCleanupDelay = 10000000;
+const TInt KHundred = 100;
+
+// ---------------------------------------------------------------------------
+// CIRStreamSource::ConnectToServerL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CIRStreamSource::ConnectToServerL( const TDesC& aUrl )
+ {
+ IRLOG_INFO2( "CIRStreamSource::ConnectToServerL - aUrl=%S", &aUrl );
+ #ifndef __WINS__
+
+ //Connecting for the first time
+ /*****************************testing*****************/
+ /*if ( iCurrentConnection )
+ {
+ iCurrentConnection->Close();
+ }
+ AsyncCleanupConnection( iCurrentConnection );
+ iCurrentConnection = NULL;*/
+/*****************************************************/
+
+ #endif //__WINS__
+ if ( iNetworkControllerHandle->GetNetworkStatus() )
+ {
+ iReConnecting = EFalse;
+ DoConnectL( aUrl );
+ }
+ else
+ {
+ iStreamSourceObserver.ErrorConnecting( KIRStreamSourceConnectionError );
+ }
+ IRLOG_DEBUG( "CIRStreamSource::ConnectToServerL - Exiting." );
+ }
+
+// ---------------------------------------------------------------------------
+// CIRStreamSource::ReconnectL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CIRStreamSource::ReconnectL( const TDesC& aUrl )
+ {
+ IRLOG_INFO( "CIRStreamSource::ReconnectL" );
+ if ( iNetworkControllerHandle->GetNetworkStatus() )
+ {
+ iReConnecting = ETrue;
+ DoConnectL( aUrl );
+ }
+ else
+ {
+ iStreamSourceObserver.ErrorConnecting( KIRStreamSourceConnectionError );
+ }
+ IRLOG_DEBUG( "CIRStreamSource::ReconnectL - Exiting." );
+ }
+
+// ---------------------------------------------------------------------------
+// CIRStreamSource::DoConnectL
+// Creates the connection object which initiates the connection
+// to the channel server
+// ---------------------------------------------------------------------------
+//
+void CIRStreamSource::DoConnectL( const TDesC& aUrl )
+ {
+ IRLOG_INFO2( "CIRStreamSource::DoConnectL iCurrentConn=%d", iCurrentConnection );
+
+ AsyncCleanupConnection( iNewConnection );
+ iNewConnection = NULL;
+ StaticConnectionCleanupCallback( this ); // delete it (and them) now
+
+ CIRStationConnection* connection = CIRStationConnection::NewL( *this, *this );
+ CleanupStack::PushL( connection );
+ iConnections.AppendL( connection );
+ CleanupStack::Pop( connection );
+ iNewConnection = connection;
+
+ iNewConnection->ConnectL( aUrl );
+
+ IRLOG_INFO2( "CIRStreamSource::DoConnectL - Exiting, iNewConnection=%d.", iNewConnection );
+ }
+
+// ---------------------------------------------------------------------------
+// CIRStreamSource::CIRStreamSource
+// Default Constructor
+// ---------------------------------------------------------------------------
+//
+CIRStreamSource::CIRStreamSource( MIRStreamSourceObserver &aObserver ):
+ iStreamSourceObserver( aObserver )
+ {
+ // no implementation
+ }
+
+// ---------------------------------------------------------------------------
+// CIRStreamSource::~CIRStreamSource
+// Default Destructor
+// ---------------------------------------------------------------------------
+//
+CIRStreamSource::~CIRStreamSource()
+ {
+ IRLOG_DEBUG( "CIRStreamSource::~CIRStreamSource" );
+
+ // close the network controller handle
+ if( iNetworkControllerHandle )
+ {
+ iNetworkControllerHandle->Close();
+ }
+ delete iSocketTimer;
+
+ delete iConnectionCleanupTimer;
+
+ iConnections.ResetAndDestroy();
+ iConnections.Close();
+ }
+
+// ---------------------------------------------------------------------------
+// CIRStreamSource::NewL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CIRStreamSource *CIRStreamSource::NewL( MIRStreamSourceObserver &aObserver )
+ {
+ CIRStreamSource *self = new( ELeave ) CIRStreamSource( aObserver );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// CIRStreamSource::ConstructL
+// ---------------------------------------------------------------------------
+//
+void CIRStreamSource::ConstructL()
+ {
+ // Open handle to network controller
+ iNetworkControllerHandle = CIRNetworkController::OpenL();
+ // create a timer for timeouts
+ iSocketTimer = CIRSocketTimeOutTimer::NewL( CActive::EPriorityHigh, *this );
+ }
+
+// ---------------------------------------------------------------------------
+// CIRStreamSource::FilltheBuffer
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CIRStreamSource::FilltheBuffer( TDes8& aInputBuffer )
+ {
+ IRLOG_DEBUG( "CIRStreamSource::FilltheBuffer" );
+
+ if( iCurrentConnection )
+ {
+ iCurrentConnection->FillBuffer( aInputBuffer );
+ }
+ else
+ {
+ iReConnecting = ETrue;
+ iStreamSourceObserver.ErrorConnecting( KIRStreamSourceNoResponse );
+ }
+ IRLOG_DEBUG( "CIRStreamSource::FilltheBuffer - Exiting." );
+ }
+
+// ---------------------------------------------------------------------------
+// CIRStreamSource::TimerExpired
+// ---------------------------------------------------------------------------
+//
+void CIRStreamSource::TimerExpired()
+ {
+ // CancelRequest gets called by UI.We could of course call it here, but you never
+ // know what it would cause in UI without thorough testing.
+ iStreamSourceObserver.ErrorConnecting( KIRStreamSourceTimeOut );
+ }
+
+// ---------------------------------------------------------------------------
+// CIRStreamSource::TimerExpired
+// ---------------------------------------------------------------------------
+//
+void CIRStreamSource::MetadataReceived( const CIRMetaData& aMetaData )
+ {
+ TRAP_IGNORE( iStreamSourceObserver.HandleMetaDataReceivedL( aMetaData ) )
+ }
+
+// ---------------------------------------------------------------------------
+// CIRStreamSource::AudioDataEvent
+// ---------------------------------------------------------------------------
+//
+void CIRStreamSource::AudioDataEvent( const TInt aResponseCode, TInt aValue )
+ {
+ IRLOG_DEBUG3( "CIRStreamSource::AudioDataEvent - aResponseCode=%d, aFeedValue=%d", aResponseCode, aValue );
+ switch( aResponseCode )
+ {
+ case EBufferFilled:
+ {
+ IRLOG_DEBUG( "CIRStreamSource::AudioDataEvent - EBufferFilled" );
+ // Indicate the observer
+ if( !iReConnecting )
+ {
+ iStreamSourceObserver.PlayNow();
+ }
+ else
+ {
+ iStreamSourceObserver.Play();
+ }
+ }
+ break;
+ case EOpenComplete:
+ {
+ IRLOG_DEBUG( "CIRStreamSource::AudioDataEvent - EOpenComplete" );
+ // Indicate the observer that streamsource buffering complete
+ iStreamSourceObserver.OpenComplete();
+ }
+ break;
+ case EBufferPercentage:
+ {
+ // Indicate buffering progress to observer
+ iStreamSourceObserver.UpdateProgress( aValue );
+ if ( aValue == KHundred )
+ {
+ IRLOG_INFO( "CIRStreamSource::AudioDataEvent - 100 percent EBufferPercentage" );
+ iSocketTimer->Cancel();
+ }
+ }
+ break;
+ default:
+ {
+ __ASSERT_DEBUG( EFalse, User::Invariant() );
+ }
+ break;
+ }
+ IRLOG_DEBUG( "CIRStreamSource::AudioDataEvent - Exiting." );
+ }
+
+// ---------------------------------------------------------------------------
+// CIRStreamSource::ContentTypeL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C const TDesC8& CIRStreamSource::ContentTypeL()
+ {
+ __ASSERT_ALWAYS( iCurrentConnection, User::Leave( KErrNotReady ) );
+
+ return iCurrentConnection->ContentType();
+ }
+
+// ---------------------------------------------------------------------------
+// CIRStreamSource::CancelRequest
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CIRStreamSource::CancelRequest()
+ {
+ IRLOG_INFO3( "CIRStreamSource::CancelRequest - iNewConnection=%d, iCurrentConnection=%d", iNewConnection, iCurrentConnection );
+ iSocketTimer->Cancel();
+
+ if ( iNewConnection )
+ {
+ iNewConnection->Close();
+ AsyncCleanupConnection( iNewConnection );
+ iNewConnection = NULL;
+ }
+ else
+ {
+ if ( iCurrentConnection )
+ {
+ iCurrentConnection->Close();
+ }
+ AsyncCleanupConnection( iCurrentConnection );
+ iCurrentConnection = NULL;
+ }
+ IRLOG_DEBUG( "CIRStreamSource::CancelRequest - Exiting." );
+ }
+
+// ---------------------------------------------------------------------------
+// CIRStreamSource::ConnectionSuccessfulL
+// ---------------------------------------------------------------------------
+//
+void CIRStreamSource::ConnectionSuccessful( CIRStationConnection* aConnection )
+ {
+ IRLOG_INFO3( "CIRStreamSource::ConnectionSuccessful aConnection=%d, iCurrentConn=%d",
+ aConnection, iCurrentConnection );
+ __ASSERT_DEBUG( aConnection->ConnectionType() == CIRStationConnection::EIRCandidate,
+ User::Invariant() );
+
+ // publish the url
+ RProperty::Set( KUidActiveInternetRadioApp, KIRPSChannelUrl, aConnection->Uri() );
+
+ if( !iReConnecting )
+ {
+ iStreamSourceObserver.StopBuffering();
+ }
+
+ if ( iCurrentConnection )
+ {
+ iCurrentConnection->Close();
+ }
+ AsyncCleanupConnection( iCurrentConnection );
+ iCurrentConnection = NULL;
+
+ aConnection->SetConnectionType( CIRStationConnection::EIRPermanent );
+ iCurrentConnection = aConnection;
+ iNewConnection = NULL;
+
+ iStreamSourceObserver.ConnectionEstablished();
+ // Buffering starts now, so let's set the timer.
+ TTimeIntervalMicroSeconds32 timeOut( KBufferingTimeOut );
+ iSocketTimer->Cancel();
+ iSocketTimer->After( timeOut );
+
+ IRLOG_DEBUG( "CIRStreamSource::ConnectionSuccessful - Exiting." );
+ }
+
+// ---------------------------------------------------------------------------
+// CIRStreamSource::ConnectionError
+// ---------------------------------------------------------------------------
+//
+void CIRStreamSource::ConnectionError( CIRStationConnection* aConnection, TInt aErrorCode )
+ {
+ IRLOG_ERROR3( "CIRStreamSource::ConnectionError - aConnection=%d, aErrorCode=%d", aConnection, aErrorCode );
+
+ if ( aConnection->ConnectionType() == CIRStationConnection::EIRCandidate )
+ {
+ AsyncCleanupConnection( aConnection );
+ iNewConnection = NULL; // To Do: implement more sophisticated pending connection handling.
+ iReConnecting = ETrue;
+ }
+ else
+ {
+ if ( aErrorCode == KIRStreamSourceDisconnected )
+ {
+ CancelRequest();
+ }
+ }
+ iStreamSourceObserver.ErrorConnecting( aErrorCode );
+ IRLOG_DEBUG( "CIRStreamSource::ConnectionError - Exiting." );
+ }
+
+// ---------------------------------------------------------------------------
+// CIRStreamSource::AsyncCleanupConnection
+// ---------------------------------------------------------------------------
+//
+void CIRStreamSource::AsyncCleanupConnection( CIRStationConnection* aConnection )
+ {
+ IRLOG_DEBUG2( "CIRStreamSource::AsyncCleanupConnection - aConnection=%d.", aConnection );
+ // let's not double-add any connections.
+ if ( aConnection )
+ {
+ IRLOG_INFO2( "CIRStreamSource::AsyncCleanupConnection - Scheduled deletion of connection %d.", aConnection );
+ delete iConnectionCleanupTimer;
+ iConnectionCleanupTimer = NULL;
+ TRAPD( err, iConnectionCleanupTimer = CPeriodic::NewL( CActive::EPriorityStandard ) )
+ if ( err == KErrNone )
+ {
+ iConnectionCleanupTimer->Start( KIRSCConnectionCleanupDelay, 0,
+ TCallBack( StaticConnectionCleanupCallback, this ) );
+ }
+ else
+ {
+ IRLOG_ERROR2( "CIRStreamSource::AsyncCleanupConnection - CPeriodic creation left with %d.", err );
+ // delete the existing dying connections.
+ StaticConnectionCleanupCallback( this );
+ }
+ aConnection->SetConnectionType( CIRStationConnection::EIRDying );
+ }
+ IRLOG_DEBUG( "CIRStreamSource::AsyncCleanupConnection - Exiting." );
+ }
+
+// ---------------------------------------------------------------------------
+// CIRStreamSource::StaticConnectionCleanupCallback
+// ---------------------------------------------------------------------------
+//
+TInt CIRStreamSource::StaticConnectionCleanupCallback( TAny* aSelfPtr )
+ {
+ CIRStreamSource* self = reinterpret_cast<CIRStreamSource*>( aSelfPtr );
+ if ( self )
+ {
+ IRRDEBUG2("CIRStreamSource::StaticConnectionCleanupCallback - Entering", KNullDesC );
+
+ IRLOG_DEBUG( "CIRStreamSource::StaticConnectionCleanupCallback." );
+ delete self->iConnectionCleanupTimer;
+ self->iConnectionCleanupTimer = NULL;
+ TInt it = self->iConnections.Count() - 1;
+ while ( it >= 0 )
+ {
+ if ( self->iConnections[it]->ConnectionType() == CIRStationConnection::EIRDying )
+ {
+ IRRDEBUG2("CIRStreamSource::StaticConnectionCleanupCallback - Entering1", KNullDesC );
+ IRLOG_INFO2( "CIRStreamSource::StaticConnectionCleanupCallback - Deleting connection %d.",
+ self->iConnections[it] );
+ delete self->iConnections[it];
+ self->iConnections.Remove( it );
+ IRRDEBUG2("CIRStreamSource::StaticConnectionCleanupCallback - Exiting1", KNullDesC );
+
+ }
+ it--;
+ }
+ IRRDEBUG2("CIRStreamSource::StaticConnectionCleanupCallback - Exiting", KNullDesC );
+
+ IRLOG_DEBUG( "CIRStreamSource::StaticConnectionCleanupCallback - Exiting." );
+ }
+ return KErrNone;
+ }
+