ITANetAudioStreamingServer.cpp 5.49 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 23 24 25

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

CITANetAudioStreamingServer::CITANetAudioStreamingServer()
	: m_pInputStream( NULL )
	, m_iUpdateStrategy( AUTO )
26
	, m_pConnection( NULL )
27
	, 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
{
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
33 34 35
	if( !m_pInputStream )
		ITA_EXCEPT1( MODAL_EXCEPTION, "Can not start server without a valid input stream" );

36
	if( !m_pNetAudioServer->Start( sAddress, iPort ) ) // blocking
37 38
		return false;

39
	m_pConnection = m_pNetAudioServer->GetConnection();
40

41 42
	m_pMessage = new CITANetAudioMessage( m_pConnection->GetByteorderSwapFlag() );
	m_pMessage->ResetMessage();
43
	m_pMessage->SetConnection( m_pConnection );
44
	m_pMessage->ReadMessage(); // blocking
45

Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen 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;
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen 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

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

Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen 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
}

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

78 79
	int iMsgType = m_pMessage->GetMessageType();
	switch( iMsgType )
80 81
	{
	case CITANetAudioProtocol::NP_CLIENT_WAITING_FOR_SAMPLES:
82 83
	{
		int iFreeSamples = m_pMessage->ReadInt();
84

85
		if( iFreeSamples >= int( m_pInputStream->GetBlocklength() ) )
86
		{
87
			// Send Samples
88
			for( int i = 0; i < int( m_pInputStream->GetNumberOfChannels() ); i++ )
89 90
			{
				ITAStreamInfo oStreamInfo;
Anne's avatar
Anne committed
91
				oStreamInfo.nSamples = m_sfTempTransmitBuffer.GetLength();
92
				const float* pfData = m_pInputStream->GetBlockPointer( i, &oStreamInfo );
93 94
				if( pfData != 0 )
					m_sfTempTransmitBuffer[ i ].write( pfData, m_sfTempTransmitBuffer.GetLength() );
95
			}
Anne's avatar
Anne committed
96
			m_pInputStream->IncrementBlockPointer();
97
			m_pMessage->SetAnswerType( CITANetAudioProtocol::NP_SERVER_SEND_SAMPLES );
Anne's avatar
Anne committed
98
			m_pMessage->WriteSampleFrame( &m_sfTempTransmitBuffer );
Anne's avatar
Anne committed
99
			m_pMessage->WriteAnswer();
100 101 102 103 104

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

#ifdef NET_AUDIO_SHOW_TRAFFIC
			vstr::out() << "[ITANetAudioStreamingServer] Not enough free samples in client buffer, requesting a trigger when more free samples available" << std::endl;
#endif

Anne's avatar
Anne committed
116
			break;
117 118 119 120
		}

		break;
	}
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
121
	case CITANetAudioProtocol::NP_CLIENT_CLOSE:
122
	{
Anne Heimes's avatar
Anne Heimes committed
123 124 125 126 127
		//m_pMessage->SetAnswerType( CITANetAudioProtocol::NP_SERVER_CLOSE );
		//m_pMessage->WriteAnswer();
		StopGently(false);
		//m_pConnection = NULL;
		
Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
128 129 130
		Stop();

		return false;
131
	}
132 133
	default:
	{
134
		vstr::out() << "[ITANetAudioStreamingServer] Unkown protocol type : " << iMsgType << std::endl;
135 136 137
		break;
	}
	}
138

Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
139 140 141
	return true;
}

142 143 144 145 146 147 148 149 150 151 152 153
void CITANetAudioStreamingServer::SetInputStream( ITADatasource* pInStream )
{
	if( VistaThreadLoop::IsRunning() )
		ITA_EXCEPT1( MODAL_EXCEPTION, "Streaming loop already running, can not change input stream" );

	m_pInputStream = pInStream;
	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();
}

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

159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
int CITANetAudioStreamingServer::GetNetStreamBlocklength() const
{
	return m_sfTempTransmitBuffer.GetLength();
}

int CITANetAudioStreamingServer::GetNetStreamNumberOfChannels() const
{
	return m_sfTempTransmitBuffer.channels();
}

void CITANetAudioStreamingServer::SetAutomaticUpdateRate()
{
	m_iUpdateStrategy = AUTO;
}

bool CITANetAudioStreamingServer::IsClientConnected() const
{
	return m_pNetAudioServer->IsConnected();
}

std::string CITANetAudioStreamingServer::GetNetworkAddress() const
{
	return m_pNetAudioServer->GetServerAddress();
}

int CITANetAudioStreamingServer::GetNetworkPort() const
{
	return m_pNetAudioServer->GetNetworkPort();
}

void CITANetAudioStreamingServer::Stop()
Anne's avatar
Anne committed
190
{
191
	m_pNetAudioServer->Stop();
Anne's avatar
Anne committed
192
}