internetradio2.0/streamsourcesrc/irstreamsource.cpp
changeset 14 896e9dbc5f19
parent 12 608f67c22514
child 15 065198191975
equal deleted inserted replaced
12:608f67c22514 14:896e9dbc5f19
     1 /*
       
     2 * Copyright (c) 2006-2007 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Stream source main class implementation
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <e32property.h>
       
    20 #include "irpubsubkeys.h"
       
    21 
       
    22 #include "irdebug.h"
       
    23 #include "irnetworkcontroller.h"
       
    24 #include "irstreamsource.h"
       
    25 #include "irstreamsourceerrors.h"
       
    26 #include "irstreamsourceobserver.h"
       
    27 #include "irstationconnection.h"
       
    28 
       
    29 
       
    30 // Constants
       
    31 const TInt KIRSCConnectionCleanupDelay = 10000000;
       
    32 const TInt KHundred = 100;
       
    33 
       
    34 // ---------------------------------------------------------------------------
       
    35 //  CIRStreamSource::ConnectToServerL
       
    36 // ---------------------------------------------------------------------------
       
    37 //
       
    38 EXPORT_C void CIRStreamSource::ConnectToServerL( const TDesC& aUrl )
       
    39     {
       
    40     IRLOG_INFO2( "CIRStreamSource::ConnectToServerL - aUrl=%S", &aUrl );
       
    41 	#ifndef __WINS__
       
    42 	 					 	 
       
    43     //Connecting for the first time
       
    44  /*****************************testing*****************/
       
    45     	/*if ( iCurrentConnection )	
       
    46 	    {
       
    47 	    iCurrentConnection->Close();
       
    48 	    }
       
    49 	AsyncCleanupConnection( iCurrentConnection );
       
    50     iCurrentConnection = NULL;*/
       
    51 /*****************************************************/
       
    52    	
       
    53    		#endif //__WINS__
       
    54     if ( iNetworkControllerHandle->GetNetworkStatus() )
       
    55         {
       
    56         iReConnecting = EFalse;
       
    57         DoConnectL( aUrl );    
       
    58         }
       
    59     else
       
    60 	    {
       
    61 		iStreamSourceObserver.ErrorConnecting( KIRStreamSourceConnectionError );
       
    62 	    }
       
    63     IRLOG_DEBUG( "CIRStreamSource::ConnectToServerL - Exiting." );
       
    64 	}
       
    65 
       
    66 // ---------------------------------------------------------------------------
       
    67 //  CIRStreamSource::ReconnectL
       
    68 // ---------------------------------------------------------------------------
       
    69 //
       
    70 EXPORT_C void CIRStreamSource::ReconnectL( const TDesC& aUrl )
       
    71     {
       
    72     IRLOG_INFO( "CIRStreamSource::ReconnectL" );
       
    73 	if ( iNetworkControllerHandle->GetNetworkStatus() )
       
    74 	    {
       
    75         iReConnecting = ETrue;
       
    76         DoConnectL( aUrl );
       
    77 	    }
       
    78 	else
       
    79 		{
       
    80 		iStreamSourceObserver.ErrorConnecting( KIRStreamSourceConnectionError );
       
    81 		}
       
    82     IRLOG_DEBUG( "CIRStreamSource::ReconnectL - Exiting." );
       
    83 	}
       
    84 	
       
    85 // ---------------------------------------------------------------------------
       
    86 //  CIRStreamSource::DoConnectL
       
    87 //  Creates the connection object which initiates the connection
       
    88 //  to the channel server
       
    89 // ---------------------------------------------------------------------------
       
    90 //
       
    91 void CIRStreamSource::DoConnectL( const TDesC& aUrl )
       
    92 	{
       
    93     IRLOG_INFO2( "CIRStreamSource::DoConnectL iCurrentConn=%d", iCurrentConnection );	
       
    94 
       
    95     AsyncCleanupConnection( iNewConnection );
       
    96     iNewConnection = NULL;        
       
    97     StaticConnectionCleanupCallback( this ); // delete it (and them) now
       
    98 
       
    99     CIRStationConnection* connection = CIRStationConnection::NewL( *this, *this );
       
   100     CleanupStack::PushL( connection );
       
   101     iConnections.AppendL( connection );
       
   102     CleanupStack::Pop( connection );
       
   103     iNewConnection = connection;
       
   104     
       
   105     iNewConnection->ConnectL( aUrl );
       
   106     
       
   107 	IRLOG_INFO2( "CIRStreamSource::DoConnectL - Exiting, iNewConnection=%d.", iNewConnection );
       
   108 	}
       
   109 
       
   110 // ---------------------------------------------------------------------------
       
   111 //  CIRStreamSource::CIRStreamSource
       
   112 //  Default Constructor
       
   113 // ---------------------------------------------------------------------------
       
   114 //
       
   115 CIRStreamSource::CIRStreamSource( MIRStreamSourceObserver &aObserver ):
       
   116 	iStreamSourceObserver( aObserver )
       
   117     {
       
   118 	// no implementation
       
   119     }
       
   120 
       
   121 // ---------------------------------------------------------------------------
       
   122 // CIRStreamSource::~CIRStreamSource
       
   123 // Default Destructor
       
   124 // ---------------------------------------------------------------------------
       
   125 //
       
   126 CIRStreamSource::~CIRStreamSource()
       
   127     {    
       
   128     IRLOG_DEBUG( "CIRStreamSource::~CIRStreamSource" );
       
   129 	
       
   130     // close the network controller handle	
       
   131 	if( iNetworkControllerHandle )
       
   132 		{
       
   133 		iNetworkControllerHandle->Close();	
       
   134         }
       
   135 	delete iSocketTimer;
       
   136     
       
   137     delete iConnectionCleanupTimer;
       
   138     
       
   139     iConnections.ResetAndDestroy();
       
   140     iConnections.Close();
       
   141     }
       
   142 
       
   143 // --------------------------------------------------------------------------- 
       
   144 //  CIRStreamSource::NewL
       
   145 // ---------------------------------------------------------------------------
       
   146 //
       
   147 EXPORT_C CIRStreamSource *CIRStreamSource::NewL( MIRStreamSourceObserver   &aObserver )
       
   148     {
       
   149     CIRStreamSource *self = new( ELeave ) CIRStreamSource( aObserver );
       
   150     CleanupStack::PushL( self );
       
   151     self->ConstructL();
       
   152     CleanupStack::Pop( self );
       
   153     return self;
       
   154     }
       
   155 
       
   156 // ---------------------------------------------------------------------------
       
   157 // CIRStreamSource::ConstructL
       
   158 // ---------------------------------------------------------------------------
       
   159 //
       
   160 void CIRStreamSource::ConstructL()
       
   161     {
       
   162     // Open handle to network controller
       
   163     iNetworkControllerHandle = CIRNetworkController::OpenL();
       
   164     // create a timer for timeouts
       
   165     iSocketTimer = CIRSocketTimeOutTimer::NewL( CActive::EPriorityHigh,	*this ); 
       
   166     }
       
   167 
       
   168 // --------------------------------------------------------------------------- 
       
   169 //  CIRStreamSource::FilltheBuffer
       
   170 // ---------------------------------------------------------------------------
       
   171 //
       
   172 EXPORT_C void CIRStreamSource::FilltheBuffer( TDes8& aInputBuffer )
       
   173     {
       
   174     IRLOG_DEBUG( "CIRStreamSource::FilltheBuffer" );
       
   175 
       
   176     if( iCurrentConnection )
       
   177     	{
       
   178    	 	iCurrentConnection->FillBuffer( aInputBuffer );
       
   179     	}
       
   180     else
       
   181     	{
       
   182     	iReConnecting = ETrue;
       
   183     	iStreamSourceObserver.ErrorConnecting( KIRStreamSourceNoResponse );
       
   184     	}
       
   185     IRLOG_DEBUG( "CIRStreamSource::FilltheBuffer - Exiting." );
       
   186     }
       
   187 
       
   188 // ---------------------------------------------------------------------------
       
   189 // CIRStreamSource::TimerExpired
       
   190 // ---------------------------------------------------------------------------
       
   191 //
       
   192 void CIRStreamSource::TimerExpired()
       
   193 	{
       
   194 	// CancelRequest gets called by UI.We could of course call it here, but you never
       
   195 	// know what it would cause in UI without thorough testing.
       
   196 	iStreamSourceObserver.ErrorConnecting( KIRStreamSourceTimeOut );
       
   197 	}
       
   198 
       
   199 // ---------------------------------------------------------------------------
       
   200 // CIRStreamSource::TimerExpired
       
   201 // ---------------------------------------------------------------------------
       
   202 //
       
   203 void CIRStreamSource::MetadataReceived( const CIRMetaData& aMetaData )
       
   204     {
       
   205     TRAP_IGNORE( iStreamSourceObserver.HandleMetaDataReceivedL( aMetaData ) )
       
   206     }
       
   207 
       
   208 // ---------------------------------------------------------------------------
       
   209 // CIRStreamSource::AudioDataEvent
       
   210 // ---------------------------------------------------------------------------
       
   211 //
       
   212 void CIRStreamSource::AudioDataEvent( const TInt aResponseCode,	TInt aValue )
       
   213 	{
       
   214 	IRLOG_DEBUG3( "CIRStreamSource::AudioDataEvent - aResponseCode=%d, aFeedValue=%d", aResponseCode, aValue );
       
   215 	switch( aResponseCode )
       
   216 		{
       
   217 		case EBufferFilled:
       
   218 			{
       
   219 			IRLOG_DEBUG( "CIRStreamSource::AudioDataEvent - EBufferFilled" );
       
   220 			// Indicate the observer
       
   221 			if( !iReConnecting )
       
   222 				{
       
   223 				iStreamSourceObserver.PlayNow();
       
   224 				}
       
   225 			else
       
   226 				{
       
   227 				iStreamSourceObserver.Play();	
       
   228 				}
       
   229 			}
       
   230 			break;
       
   231 		case EOpenComplete:
       
   232 			{
       
   233 			IRLOG_DEBUG( "CIRStreamSource::AudioDataEvent - EOpenComplete" );
       
   234 			// Indicate the observer that streamsource buffering complete	
       
   235 			iStreamSourceObserver.OpenComplete();
       
   236 			}
       
   237 			break;
       
   238 		case EBufferPercentage:
       
   239 			{
       
   240 			// Indicate buffering progress to observer
       
   241 			iStreamSourceObserver.UpdateProgress( aValue );
       
   242 			if ( aValue == KHundred )
       
   243 				{
       
   244 			    IRLOG_INFO( "CIRStreamSource::AudioDataEvent - 100 percent EBufferPercentage" );				
       
   245 				iSocketTimer->Cancel();
       
   246 				} 
       
   247 			}
       
   248 			break;
       
   249 		default:
       
   250 			{
       
   251 			__ASSERT_DEBUG( EFalse, User::Invariant() );
       
   252 			}
       
   253 			break;	
       
   254 		}
       
   255 	IRLOG_DEBUG( "CIRStreamSource::AudioDataEvent - Exiting." );	
       
   256 	}
       
   257 	
       
   258 // ---------------------------------------------------------------------------
       
   259 //  CIRStreamSource::ContentTypeL
       
   260 // ---------------------------------------------------------------------------
       
   261 //
       
   262 EXPORT_C const TDesC8& CIRStreamSource::ContentTypeL()
       
   263 	{
       
   264     __ASSERT_ALWAYS( iCurrentConnection, User::Leave( KErrNotReady ) );
       
   265 
       
   266     return iCurrentConnection->ContentType();
       
   267 	}
       
   268 
       
   269 // ---------------------------------------------------------------------------
       
   270 // CIRStreamSource::CancelRequest
       
   271 // ---------------------------------------------------------------------------
       
   272 //
       
   273 EXPORT_C void CIRStreamSource::CancelRequest()
       
   274 	{
       
   275 	IRLOG_INFO3( "CIRStreamSource::CancelRequest - iNewConnection=%d, iCurrentConnection=%d", iNewConnection, iCurrentConnection );	
       
   276 	iSocketTimer->Cancel();
       
   277 		
       
   278     if ( iNewConnection )		
       
   279         {
       
   280         iNewConnection->Close();
       
   281         AsyncCleanupConnection( iNewConnection );
       
   282         iNewConnection = NULL;
       
   283         }
       
   284     else
       
   285         {
       
   286 		if ( iCurrentConnection )
       
   287 		    {
       
   288 		    iCurrentConnection->Close();		    
       
   289 		    }
       
   290 		AsyncCleanupConnection( iCurrentConnection );
       
   291 		iCurrentConnection = NULL;
       
   292         }        
       
   293 	IRLOG_DEBUG( "CIRStreamSource::CancelRequest - Exiting." );	
       
   294 	}
       
   295 
       
   296 // ---------------------------------------------------------------------------
       
   297 // CIRStreamSource::ConnectionSuccessfulL
       
   298 // ---------------------------------------------------------------------------
       
   299 //
       
   300 void CIRStreamSource::ConnectionSuccessful( CIRStationConnection* aConnection )
       
   301 	{
       
   302 	IRLOG_INFO3( "CIRStreamSource::ConnectionSuccessful aConnection=%d, iCurrentConn=%d", 
       
   303 	             aConnection, iCurrentConnection );	
       
   304 	__ASSERT_DEBUG( aConnection->ConnectionType() == CIRStationConnection::EIRCandidate,
       
   305 	                User::Invariant() );
       
   306 	                
       
   307     // publish the url
       
   308     RProperty::Set( KUidActiveInternetRadioApp, KIRPSChannelUrl, aConnection->Uri() );	
       
   309 
       
   310 	if( !iReConnecting )
       
   311 		{
       
   312 		iStreamSourceObserver.StopBuffering();
       
   313 	    }	
       
   314 	    
       
   315 	if ( iCurrentConnection )	
       
   316 	    {
       
   317 	    iCurrentConnection->Close();
       
   318 	    }
       
   319 	AsyncCleanupConnection( iCurrentConnection );
       
   320     iCurrentConnection = NULL;
       
   321 
       
   322     aConnection->SetConnectionType( CIRStationConnection::EIRPermanent );
       
   323     iCurrentConnection = aConnection;
       
   324     iNewConnection = NULL;
       
   325 
       
   326     iStreamSourceObserver.ConnectionEstablished();
       
   327     // Buffering starts now, so let's set the timer.
       
   328 	TTimeIntervalMicroSeconds32 timeOut( KBufferingTimeOut );
       
   329 	iSocketTimer->Cancel();
       
   330 	iSocketTimer->After( timeOut );
       
   331 
       
   332 	IRLOG_DEBUG( "CIRStreamSource::ConnectionSuccessful - Exiting." );	
       
   333 	}
       
   334 
       
   335 // ---------------------------------------------------------------------------
       
   336 // CIRStreamSource::ConnectionError
       
   337 // ---------------------------------------------------------------------------
       
   338 //
       
   339 void CIRStreamSource::ConnectionError( CIRStationConnection* aConnection, TInt aErrorCode )
       
   340 	{
       
   341 	IRLOG_ERROR3( "CIRStreamSource::ConnectionError - aConnection=%d, aErrorCode=%d", aConnection, aErrorCode );
       
   342     
       
   343 	if ( aConnection->ConnectionType() == CIRStationConnection::EIRCandidate )
       
   344 	    {
       
   345         AsyncCleanupConnection( aConnection );
       
   346         iNewConnection = NULL; // To Do: implement more sophisticated pending connection handling.	    
       
   347 		iReConnecting = ETrue;        
       
   348 	    }
       
   349     else
       
   350         {
       
   351         if ( aErrorCode == KIRStreamSourceDisconnected )
       
   352             {
       
   353 			CancelRequest();            
       
   354             }
       
   355         }	    
       
   356 	iStreamSourceObserver.ErrorConnecting( aErrorCode );
       
   357 	IRLOG_DEBUG( "CIRStreamSource::ConnectionError - Exiting." );
       
   358 	}
       
   359 
       
   360 // ---------------------------------------------------------------------------
       
   361 // CIRStreamSource::AsyncCleanupConnection
       
   362 // ---------------------------------------------------------------------------
       
   363 //
       
   364 void CIRStreamSource::AsyncCleanupConnection( CIRStationConnection* aConnection )
       
   365     {
       
   366     IRLOG_DEBUG2( "CIRStreamSource::AsyncCleanupConnection - aConnection=%d.", aConnection );    
       
   367     // let's not double-add any connections.
       
   368     if ( aConnection )
       
   369         {
       
   370         IRLOG_INFO2( "CIRStreamSource::AsyncCleanupConnection - Scheduled deletion of connection %d.", aConnection );            
       
   371         delete iConnectionCleanupTimer;
       
   372         iConnectionCleanupTimer = NULL;
       
   373         TRAPD( err, iConnectionCleanupTimer = CPeriodic::NewL( CActive::EPriorityStandard ) )
       
   374         if ( err == KErrNone )
       
   375             {
       
   376             iConnectionCleanupTimer->Start( KIRSCConnectionCleanupDelay, 0,
       
   377             			 TCallBack( StaticConnectionCleanupCallback, this ) );
       
   378             }
       
   379         else
       
   380             {
       
   381             IRLOG_ERROR2( "CIRStreamSource::AsyncCleanupConnection - CPeriodic creation left with %d.", err );
       
   382             // delete the existing dying connections.
       
   383             StaticConnectionCleanupCallback( this );    
       
   384             }
       
   385         aConnection->SetConnectionType( CIRStationConnection::EIRDying );                    
       
   386         }
       
   387     IRLOG_DEBUG( "CIRStreamSource::AsyncCleanupConnection - Exiting." );                    
       
   388     }
       
   389 
       
   390 // ---------------------------------------------------------------------------
       
   391 // CIRStreamSource::StaticConnectionCleanupCallback
       
   392 // ---------------------------------------------------------------------------
       
   393 //
       
   394 TInt CIRStreamSource::StaticConnectionCleanupCallback( TAny* aSelfPtr )
       
   395 	{
       
   396 	CIRStreamSource* self = reinterpret_cast<CIRStreamSource*>( aSelfPtr );
       
   397 	if ( self )
       
   398 		{
       
   399 	IRRDEBUG2("CIRStreamSource::StaticConnectionCleanupCallback - Entering", KNullDesC );
       
   400 
       
   401         IRLOG_DEBUG( "CIRStreamSource::StaticConnectionCleanupCallback." );
       
   402 		delete self->iConnectionCleanupTimer;
       
   403 		self->iConnectionCleanupTimer = NULL;
       
   404 		TInt it = self->iConnections.Count() - 1;
       
   405 		while ( it >= 0 )
       
   406 		    {
       
   407 		    if ( self->iConnections[it]->ConnectionType() == CIRStationConnection::EIRDying )
       
   408 		        {
       
   409 		 IRRDEBUG2("CIRStreamSource::StaticConnectionCleanupCallback - Entering1", KNullDesC );
       
   410         IRLOG_INFO2( "CIRStreamSource::StaticConnectionCleanupCallback - Deleting connection %d.", 
       
   411                 self->iConnections[it] );		    		        
       
   412         delete self->iConnections[it];
       
   413         self->iConnections.Remove( it );
       
   414 		 IRRDEBUG2("CIRStreamSource::StaticConnectionCleanupCallback - Exiting1", KNullDesC );
       
   415 
       
   416 		        }
       
   417 		    it--;
       
   418 		    }
       
   419 	IRRDEBUG2("CIRStreamSource::StaticConnectionCleanupCallback - Exiting", KNullDesC );
       
   420 
       
   421         IRLOG_DEBUG( "CIRStreamSource::StaticConnectionCleanupCallback - Exiting." );		    
       
   422 		}
       
   423 	return KErrNone;
       
   424 	}
       
   425