ITANetAudioStreamingServer.cpp 5.66 KB
Newer Older
Anne's avatar
Anne committed
1 2
#include <ITANetAudioStreamingServer.h>
#include <ITANetAudioServer.h>
3
#include <ITANetAudioMessage.h>
Anne's avatar
Anne committed
4 5

// ITA includes
Anne's avatar
Anne committed
6
#include <ITADataSource.h>
7
#include <ITANetAudioMessage.h>
Anne's avatar
Anne committed
8 9 10 11 12 13 14 15 16
#include <ITAException.h>
#include <ITAStreamInfo.h>

// Vista includes
#include <VistaInterProcComm/Concurrency/VistaThreadLoop.h>
#include <VistaInterProcComm/Connections/VistaConnectionIP.h>
#include <VistaInterProcComm/IPNet/VistaTCPSocket.h>
#include <VistaBase/VistaTimeUtils.h>
#include <VistaInterProcComm/IPNet/VistaIPAddress.h>
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
17
#include <VistaBase/VistaStreamUtils.h>
Anne's avatar
Anne committed
18 19 20 21 22

// STL
#include <cmath>
#include <cassert>

Anne's avatar
Anne committed
23 24 25 26 27
CITANetAudioStreamingServer::CITANetAudioStreamingServer( )
: m_pInputStream( NULL )
, m_iUpdateStrategy( AUTO )
, m_pConnection( NULL )
, m_pNetAudioServer( new CITANetAudioServer( ) )
Anne's avatar
Anne committed
28 29 30
{
}

31
bool CITANetAudioStreamingServer::Start( const std::string& sAddress, int iPort )
Anne's avatar
Anne committed
32
{
Anne's avatar
Anne committed
33
	if ( !m_pInputStream )
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
34 35
		ITA_EXCEPT1( MODAL_EXCEPTION, "Can not start server without a valid input stream" );

Anne's avatar
Anne committed
36
	if ( !m_pNetAudioServer->Start( sAddress, iPort ) ) // blocking
37 38
		return false;

Anne's avatar
Anne committed
39
	m_pConnection = m_pNetAudioServer->GetConnection( );
40

Anne's avatar
Anne committed
41 42
	m_pMessage = new CITANetAudioMessage( m_pConnection->GetByteorderSwapFlag( ) );
	m_pMessage->ResetMessage( );
43
	m_pMessage->SetConnection( m_pConnection );
Anne's avatar
Anne committed
44
	while ( !m_pMessage->ReadMessage( ) ); //blocking
45

Anne's avatar
Anne committed
46 47
	assert( m_pMessage->GetMessageType( ) == CITANetAudioProtocol::NP_CLIENT_OPEN );
	CITANetAudioProtocol::StreamingParameters oClientParams = m_pMessage->ReadStreamingParameters( );
48

Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
49
	bool bOK = false;
Anne's avatar
Anne committed
50
	if ( m_oServerParams == oClientParams )
Anne's avatar
Anne committed
51
	{
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
52
		bOK = true;
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
53
#ifdef NET_AUDIO_SHOW_TRAFFIC
54
		vstr::out() << "[ITANetAudioStreamingServer] Server and client parameters matched. Will resume with streaming" << std::endl;
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
55 56 57
	}
	else
	{
58
		vstr::out() << "[ITANetAudioStreamingServer] Server and client parameters mismatch detected. Will notify client and stop." << std::endl;
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
59
#endif
Anne's avatar
Anne committed
60
	}
Anne's avatar
Anne committed
61

Anne's avatar
Anne committed
62
	m_pMessage->SetMessageType( CITANetAudioProtocol::NP_SERVER_OPEN );
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
63
	m_pMessage->WriteBool( bOK );
Anne's avatar
Anne committed
64
	m_pMessage->WriteMessage( );
65

Anne's avatar
Anne committed
66 67
	if ( bOK )
		Run( );
68

Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
69
	return bOK;
Anne's avatar
Anne committed
70 71
}

Anne's avatar
Anne committed
72
bool CITANetAudioStreamingServer::LoopBody( )
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
73
{
Anne's avatar
Anne committed
74
	m_pMessage->ResetMessage( );
75
	m_pMessage->SetConnection( m_pConnection );
Anne's avatar
Anne committed
76
	m_pMessage->ReadMessage( );
77

Anne's avatar
Anne committed
78
	if ( m_pMessage->ReadMessage( ) )
79
	{
Anne's avatar
Anne committed
80 81
		int iMsgType = m_pMessage->GetMessageType( );
		switch ( iMsgType )
82
		{
Anne's avatar
Anne committed
83
			case CITANetAudioProtocol::NP_CLIENT_WAITING_FOR_SAMPLES:
84
			{
Anne's avatar
Anne committed
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
					int iFreeSamples = m_pMessage->ReadInt( );
					if ( iFreeSamples >= int( m_pInputStream->GetBlocklength( ) ) )
					{
						// Send Samples
						for ( int i = 0; i < int( m_pInputStream->GetNumberOfChannels( ) ); i++ )
						{
							ITAStreamInfo oStreamInfo;
							oStreamInfo.nSamples = m_sfTempTransmitBuffer.GetLength( );
							const float* pfData = m_pInputStream->GetBlockPointer( i, &oStreamInfo );
							if ( pfData != 0 )
							m_sfTempTransmitBuffer[ i ].write( pfData, m_sfTempTransmitBuffer.GetLength( ) );
						}
					m_pInputStream->IncrementBlockPointer( );
					m_pMessage->SetMessageType( CITANetAudioProtocol::NP_SERVER_SEND_SAMPLES );
					m_pMessage->WriteSampleFrame( &m_sfTempTransmitBuffer );
					m_pMessage->WriteMessage( );
101 102

#ifdef NET_AUDIO_SHOW_TRAFFIC
Anne's avatar
Anne committed
103 104
					vstr::out() << "[ITANetAudioStreamingServer] Transmitted "<< m_sfTempTransmitBuffer.GetLength() << " samples for " 
					<< m_pInputStream->GetNumberOfChannels() << " channels" << std::endl;
105
#endif
Anne's avatar
Anne committed
106 107 108 109 110 111
				}
				else
				{
					// Waiting for Trigger
					m_pMessage->SetMessageType( CITANetAudioProtocol::NP_SERVER_WAITING_FOR_TRIGGER );
					m_pMessage->WriteMessage( );
112 113

#ifdef NET_AUDIO_SHOW_TRAFFIC
Anne's avatar
Anne committed
114
					vstr::out() << "[ITANetAudioStreamingServer] Not enough free samples in client buffer, requesting a trigger when more free samples available" << std::endl;
115
#endif
Anne's avatar
Anne committed
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
				}
				break;
			}
			case CITANetAudioProtocol::NP_CLIENT_CLOSE:
			{
				//m_pMessage->SetAnswerType( CITANetAudioProtocol::NP_SERVER_CLOSE );
				//m_pMessage->WriteAnswer();
				StopGently( false );
				//m_pConnection = NULL;
				Stop( );
				return false;
			}
			default:
			{
				vstr::out( ) << "[ITANetAudioStreamingServer] Unkown protocol type : " << iMsgType << std::endl;
				break;
			}
133 134
		}

135
	}
136

Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
137 138 139
	return true;
}

140 141
void CITANetAudioStreamingServer::SetInputStream( ITADatasource* pInStream )
{
Anne's avatar
Anne committed
142
	if ( VistaThreadLoop::IsRunning( ) )
143 144 145
		ITA_EXCEPT1( MODAL_EXCEPTION, "Streaming loop already running, can not change input stream" );

	m_pInputStream = pInStream;
Anne's avatar
Anne committed
146 147 148 149
	m_sfTempTransmitBuffer.init( m_pInputStream->GetNumberOfChannels( ), m_pInputStream->GetBlocklength( ), true );
	m_oServerParams.dSampleRate = m_pInputStream->GetSampleRate( );
	m_oServerParams.iBlockSize = m_pInputStream->GetBlocklength( );
	m_oServerParams.iChannels = m_pInputStream->GetNumberOfChannels( );
150 151
}

Anne's avatar
Anne committed
152
ITADatasource* CITANetAudioStreamingServer::GetInputStream( ) const
Anne's avatar
Anne committed
153 154 155 156
{
	return m_pInputStream;
}

Anne's avatar
Anne committed
157
int CITANetAudioStreamingServer::GetNetStreamBlocklength( ) const
158
{
Anne's avatar
Anne committed
159
	return m_sfTempTransmitBuffer.GetLength( );
160 161
}

Anne's avatar
Anne committed
162
int CITANetAudioStreamingServer::GetNetStreamNumberOfChannels( ) const
163
{
Anne's avatar
Anne committed
164
	return m_sfTempTransmitBuffer.channels( );
165 166
}

Anne's avatar
Anne committed
167
void CITANetAudioStreamingServer::SetAutomaticUpdateRate( )
168 169 170 171
{
	m_iUpdateStrategy = AUTO;
}

Anne's avatar
Anne committed
172
bool CITANetAudioStreamingServer::IsClientConnected( ) const
173
{
Anne's avatar
Anne committed
174
	return m_pNetAudioServer->IsConnected( );
175 176
}

Anne's avatar
Anne committed
177
std::string CITANetAudioStreamingServer::GetNetworkAddress( ) const
178
{
Anne's avatar
Anne committed
179
	return m_pNetAudioServer->GetServerAddress( );
180 181
}

Anne's avatar
Anne committed
182
int CITANetAudioStreamingServer::GetNetworkPort( ) const
183
{
Anne's avatar
Anne committed
184
	return m_pNetAudioServer->GetNetworkPort( );
185 186
}

Anne's avatar
Anne committed
187
void CITANetAudioStreamingServer::Stop( )
Anne's avatar
Anne committed
188
{
Anne's avatar
Anne committed
189
	m_pNetAudioServer->Stop( );
Anne's avatar
Anne committed
190
}