ITANetAudioStreamingClient.cpp 7.15 KB
Newer Older
Dipl.-Ing. Jonas Stienen's avatar
Running  
Dipl.-Ing. Jonas Stienen committed
1 2 3 4
#include <ITANetAudioStreamingClient.h>

#include <ITANetAudioClient.h>
#include <ITANetAudioMessage.h>
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
5
#include <ITANetAudioStream.h>
6 7
#include <ITADataLog.h>
#include <ITAClock.h>
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
8 9

#include <VistaInterProcComm/Connections/VistaConnectionIP.h>
10
#include <VistaInterProcComm/Concurrency/VistaPriority.h>
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
11
#include <VistaBase/VistaStreamUtils.h>
12
#include <VistaBase/VistaTimeUtils.h>
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
13

14 15 16 17 18 19 20 21
//! Audio streaming log item
struct ITAClientLog : public ITALogDataBase
{
	inline static std::ostream& outputDesc( std::ostream& os )
	{
		os << "BlockId";
		os << "\t" << "WorldTimeStamp";
		os << "\t" << "ProtocolStatus";
22
		os << "\t" << "TransmittedRingBufferFreeSamples";
23 24 25 26 27 28 29 30 31
		os << "\t" << "FreeSamples";
		os << std::endl;
		return os;
	};

	inline std::ostream& outputData( std::ostream& os ) const
	{
		os << uiBlockId;
		os << "\t" << std::setprecision( 12 ) << dWorldTimeStamp;
32 33
		os << "\t" << sProtocolStatus;
		os << "\t" << ( bTransmittedRingBufferFreeSamples ? "true" : "false" );
34 35 36 37 38 39 40
		os << "\t" << iFreeSamples;
		os << std::endl;
		return os;
	};

	unsigned int uiBlockId; //!< Block identifier (audio streaming)
	double dWorldTimeStamp;
41 42
	std::string sProtocolStatus;
	bool bTransmittedRingBufferFreeSamples;
43 44 45 46 47 48 49
	int iFreeSamples;

};

class ITABufferedDataLoggerImplClient : public ITABufferedDataLogger < ITAClientLog > {};


Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
50
CITANetAudioStreamingClient::CITANetAudioStreamingClient( CITANetAudioStream* pParent )
51
	: m_pStream( pParent )
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
52 53
	, m_pConnection( NULL )
	, m_bStopIndicated( false )
54
	, m_bStopped( false )
55 56 57
	, m_iStreamingBlockId( 0 )
	, m_dServerClockSyncRequestTimeInterval( 0.1f )
	, m_dServerClockSyncLastSyncTime( 0.0f )
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
58
{
Dipl.-Ing. Jonas Stienen's avatar
Running  
Dipl.-Ing. Jonas Stienen committed
59
	m_pClient = new CITANetAudioClient();
Anne's avatar
Anne committed
60
	m_oParams.iChannels = pParent->GetNumberOfChannels();
61
	m_oParams.dSampleRate = pParent->GetSampleRate();
62 63
	m_oParams.iBlockSize = pParent->GetBlocklength();
	m_oParams.iRingBufferSize = pParent->GetRingBufferSize();
Jonas Stienen's avatar
Jonas Stienen committed
64 65
		 
	m_sfReceivingBuffer.init( m_oParams.iChannels, m_oParams.iRingBufferSize, false );
66

67
	m_pMessage = new CITANetAudioMessage( VistaSerializingToolset::SWAPS_MULTIBYTE_VALUES );
Jonas Stienen's avatar
Jonas Stienen committed
68 69 70

	m_pClientLogger = new ITABufferedDataLoggerImplClient();
	SetClientLoggerBaseName( "ITANetAudioStreamingClient" );
71

72
	//SetPriority( VistaPriority::VISTA_MID_PRIORITY );
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
73 74 75 76
}

CITANetAudioStreamingClient::~CITANetAudioStreamingClient()
{
77 78 79
	if( GetIsConnected() )
		Disconnect();

80
	StopGently( false );
81 82 83 84

	delete m_pClientLogger;
	delete m_pClient;
	delete m_pMessage;
85

86 87
	vstr::out() << "[ ITANetAudioStreamingClient ] Processing statistics: " << m_swTryReadBlockStats.ToString() << std::endl;
	vstr::out() << "[ ITANetAudioStreamingClient ] Try-read access statistics: " << m_swTryReadAccessStats.ToString() << std::endl;
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
88 89 90 91
}

bool CITANetAudioStreamingClient::Connect( const std::string& sAddress, int iPort )
{
Dipl.-Ing. Jonas Stienen's avatar
Running  
Dipl.-Ing. Jonas Stienen committed
92
	if( GetIsConnected() )
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
93
		return false;
94

Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
95 96
	if( !m_pClient->Connect( sAddress, iPort ) )
		ITA_EXCEPT1( INVALID_PARAMETER, "Could not connect to " + sAddress );
97

98 99
	if( !m_pClient->GetIsConnected() )
		return false;
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
100

101
	m_pConnection = m_pClient->GetConnection();
102

103
	m_pMessage->ResetMessage();
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
104 105 106 107
	m_pMessage->SetConnection( m_pConnection );

	// Validate streaming parameters of server and client
	m_pMessage->SetMessageType( CITANetAudioProtocol::NP_CLIENT_OPEN );
Anne's avatar
Anne committed
108
	m_pMessage->WriteStreamingParameters( m_oParams );
109 110
	m_pMessage->WriteMessage();
	m_pMessage->ResetMessage();
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
111

112
	while( !m_pMessage->ReadMessage( 0 ) );
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
113

114 115 116 117 118 119
	assert( m_pMessage->GetMessageType() == CITANetAudioProtocol::NP_SERVER_OPEN );

	// Clock sync vars
	m_dServerClockSyncRequestTimeInterval = m_pMessage->ReadDouble();
	m_dServerClockSyncLastSyncTime = 0;
	
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
120 121 122 123 124 125 126
	Run();

	return true;
}

bool CITANetAudioStreamingClient::LoopBody()
{
127
	if( !GetIsConnected() )
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
128 129
		return true;

130
	ITAClientLog oLog;
131 132
	oLog.uiBlockId = ++m_iStreamingBlockId;
	oLog.iFreeSamples = m_pStream->GetRingBufferFreeSamples();
133 134
	oLog.sProtocolStatus = CITANetAudioProtocol::GetNPMessageID( CITANetAudioProtocol::NP_CLIENT_IDLE );
	oLog.bTransmittedRingBufferFreeSamples = false;
135 136

	oLog.dWorldTimeStamp = ITAClock::getDefaultClock()->getTime();
137 138 139 140 141 142

	if( m_bStopIndicated && !m_bStopped )
	{
		m_pMessage->ResetMessage();
		m_pMessage->SetMessageType( CITANetAudioProtocol::NP_CLIENT_CLOSE );
		m_pMessage->WriteMessage();
143 144 145 146 147 148 149 150 151 152

		while( true )
		{
			m_pMessage->ResetMessage();
			m_pMessage->ReadMessage( 0 );
			int iMsgType = m_pMessage->GetMessageType();
			if( iMsgType == CITANetAudioProtocol::NP_SERVER_CLOSE )
				break;
		}

153 154 155 156 157 158 159 160
		m_bStopped = true;
		m_pMessage->SetConnection( NULL );

		while( GetIsConnected() )
			VistaTimeUtils::Sleep( 100 );

		return true;
	}
Anne's avatar
Anne committed
161

162 163
	// Try-read message (blocking for a timeout of 1ms)
	m_pMessage->ResetMessage();
164 165
	m_swTryReadBlockStats.start();
	m_swTryReadAccessStats.start();
166
	if( m_pMessage->ReadMessage( 1 ) )
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
167
	{
168
		m_swTryReadAccessStats.stop();
169

Jonas Stienen's avatar
Jonas Stienen committed
170 171 172 173 174 175 176
		int iMsgType = m_pMessage->GetMessageType();
		switch( iMsgType )
		{
		case CITANetAudioProtocol::NP_SERVER_SENDING_SAMPLES:
			m_pMessage->ReadSampleFrame( &m_sfReceivingBuffer );
			if( m_pStream->GetRingBufferFreeSamples() >= m_sfReceivingBuffer.GetLength() )
				m_pStream->Transmit( m_sfReceivingBuffer, m_sfReceivingBuffer.GetLength() );
177
#ifdef NET_AUDIO_SHOW_TRAFFIC
178
			vstr::out() << "[ITANetAudioStreamingClient] Received " << m_sfReceivingBuffer.GetLength() << " samples" << std::endl;
179
#endif
Jonas Stienen's avatar
Jonas Stienen committed
180
			break;
181

Jonas Stienen's avatar
Jonas Stienen committed
182 183 184 185 186 187
		case CITANetAudioProtocol::NP_SERVER_GET_RINGBUFFER_FREE_SAMPLES:
			m_pMessage->ReadBool();
			m_pMessage->SetMessageType( CITANetAudioProtocol::NP_CLIENT_SENDING_RINGBUFFER_FREE_SAMPLES );
			m_pMessage->WriteInt( m_pStream->GetRingBufferFreeSamples() );
			m_pMessage->WriteMessage();
			break;
188

Jonas Stienen's avatar
Jonas Stienen committed
189 190 191
		case CITANetAudioProtocol::NP_SERVER_CLOSE:
			Disconnect();
			break;
192

Jonas Stienen's avatar
Jonas Stienen committed
193 194 195
		default:
			vstr::out() << "[ITANetAudioStreamingServer] Unkown protocol type : " << iMsgType << std::endl;
			break;
196

197
		}
Jonas Stienen's avatar
Jonas Stienen committed
198

199
		// Also log message type on incoming message
200
		oLog.sProtocolStatus = CITANetAudioProtocol::GetNPMessageID( iMsgType );
201

Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
202
	}
203 204
	if( m_swTryReadBlockStats.started() )
		m_swTryReadBlockStats.stop();
205 206 207 208

	// Send ring buffer free samples occasionally (as requested by server)
	const double dNow = ITAClock::getDefaultClock()->getTime();
	if( ( m_dServerClockSyncLastSyncTime + m_dServerClockSyncRequestTimeInterval ) < dNow )
209
	{
210 211 212 213
		m_pMessage->SetMessageType( CITANetAudioProtocol::NP_CLIENT_SENDING_RINGBUFFER_FREE_SAMPLES );
		m_pMessage->WriteInt( m_pStream->GetRingBufferFreeSamples() );
		m_pMessage->WriteMessage();
		m_dServerClockSyncLastSyncTime = dNow;
214
		oLog.bTransmittedRingBufferFreeSamples = true;
215
	}
216 217

	m_pClientLogger->log( oLog );
218
	
219
	return false;
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
220 221
}

Jonas Stienen's avatar
Jonas Stienen committed
222 223 224 225 226 227 228 229 230
std::string CITANetAudioStreamingClient::GetClientLoggerBaseName() const
{
	return m_sClientLoggerBaseName;
}

void CITANetAudioStreamingClient::SetClientLoggerBaseName( const std::string& sBaseName )
{
	m_sClientLoggerBaseName = sBaseName;

Anne Heimes's avatar
Anne Heimes committed
231
	m_pClientLogger->setOutputFile( m_sClientLoggerBaseName + "_Client.log" );
232
	m_pMessage->SetMessageLoggerBaseName( GetClientLoggerBaseName() + "_Messages" );
Jonas Stienen's avatar
Jonas Stienen committed
233 234
}

Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
235 236 237 238
bool CITANetAudioStreamingClient::GetIsConnected() const
{
	return m_pClient->GetIsConnected();
}
239 240 241 242 243

void CITANetAudioStreamingClient::Disconnect()
{
	m_bStopIndicated = true;

244 245
	while( !m_bStopped )
		VistaTimeUtils::Sleep( 100 );
246

247
	m_pConnection = NULL;
Anne Heimes's avatar
bugfix  
Anne Heimes committed
248
	m_pMessage->ClearConnection();
249
	m_pClient->Disconnect();
250
	m_bStopIndicated = false;
251
	m_bStopped = false;
252
}