VAServer.cpp 7.53 KB
Newer Older
1
/*
2
 *  --------------------------------------------------------------------------------------------
3
4
 *
 *    VVV        VVV A
5
6
 *     VVV      VVV AAA        Virtual Acoustics (VA)
 *      VVV    VVV   AAA       Real-time auralisation for virtual reality
7
 *       VVV  VVV     AAA
8
9
 *        VVVVVV       AAA     (c) Copyright Institute of Technical Acoustics (ITA)
 *         VVVV         AAA        RWTH Aachen University (http://www.akustik.rwth-aachen.de)
10
 *
11
 *  --------------------------------------------------------------------------------------------
12
13
14
 */

// STL includes
15
#ifdef WIN32
16
#include <conio.h>
17
18
19
20
#else
#include <ncurses.h>
#endif

21
22
23
24
25
26
#include <iostream>

// ITA includes
#include <ITAException.h>
#include <ITANumericUtils.h>
#include <ITAStringUtils.h>
27
#include <ITAFileSystemUtils.h>
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

// VA includes
#include <VACore.h>
#include <VACoreFactory.h>
#include <VACoreVersion.h>
#include <VAException.h>
#include <VANetServer.h>
#include <VANetUtils.h>

using namespace std;

int main( int argc, char* argv[] )
{

	// Arguments
43
44

	bool bVersionInfoRequest = false;
45
	std::string sServerAddress, sVACoreConfigPath;
46

47
48
49
	if( argc == 1 )
	{
		sServerAddress = "0.0.0.0:12340";
50
		cout << "[ VAServer  ] No bind address and port given, using default: " << sServerAddress << endl;
51
		string sDefaultConfigFile = "VACore.ini";
52
		if( doesFileExist( sDefaultConfigFile ) )
53
54
		{
			sVACoreConfigPath = sDefaultConfigFile;
55
			cout << "[ VAServer  ] Using default configuration file '" << sVACoreConfigPath << "'." << endl;
56
57
58
59
		}
	}
	else
	{
60
61
62
63
64
65
66
		if( argc == 2 )
		{
			const string sCommand( argv[ 1 ] );
			if( sCommand == "--version" || sCommand == "-v" || sCommand == "-version" )
				bVersionInfoRequest = true;
		}

67
		if( argc >= 2 )
68
			sServerAddress = argv[ 1 ];
69
		if( argc >= 3 )
70
			sVACoreConfigPath = argv[ 2 ];
71
72
	}

73
74
75


	// Core
76
77

	IVACore* pCore = NULL;
78
	IVANetServer* pServer = NULL;
79

80
	try
81
82
83
84
85
	{
		int ec;
		if( sVACoreConfigPath.empty() )
		{
			CVAStruct oDefaultCoreConfig, oAudioDriver, oRenderer, oReproduction, oOutput, oOutputDevice;
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109

			oAudioDriver[ "Driver" ] = "Portaudio";
			oAudioDriver[ "Device" ] = "default";
			oDefaultCoreConfig[ "Audio driver" ] = oAudioDriver;

			oRenderer[ "Class" ] = "BinauralFreefield";
			oRenderer[ "Enabled" ] = true;
			oRenderer[ "Outputs" ] = "DefaultTalkthrough";
			oDefaultCoreConfig[ "Renderer:DefaultBinauralFreefield" ] = oRenderer;

			oReproduction[ "Class" ] = "Talkthrough";
			oReproduction[ "Enabled" ] = true;
			oReproduction[ "Name" ] = "Default talkthrough reproduction";
			oReproduction[ "Outputs" ] = "DefaultOutput";
			oDefaultCoreConfig[ "Reproduction:DefaultTalkthrough" ] = oReproduction;

			oOutput[ "Devices" ] = "DefaultStereoChannels";
			oOutput[ "Description" ] = "Default stereo channels (headphones)";
			oDefaultCoreConfig[ "Output:DefaultOutput" ] = oOutput;

			oOutputDevice[ "Type" ] = "HP";
			oOutputDevice[ "Description" ] = "Default headphone hardware device (two-channels)";
			oOutputDevice[ "Channels" ] = "1,2";
			oDefaultCoreConfig[ "OutputDevice:DefaultStereoChannels" ] = oOutputDevice;
110
111
112
113
114

			pCore = VACore::CreateCoreInstance( oDefaultCoreConfig );
		}
		else
		{
115
			cout << "[ VAServer  ] Core configuration path: " << correctPath( sVACoreConfigPath ) << endl;
116
117
118
			pCore = VACore::CreateCoreInstance( sVACoreConfigPath );
		}

119
120
121
		// If only version requested, exit.
		if( bVersionInfoRequest )
		{
122
123
			CVACoreVersionInfo ver;
			pCore->GetVersionInfo( &ver );
124
			cout << "[ VAServer  ] " << ver.ToString() << endl;
125

126
127
128
129
			delete pCore;
			return 0;
		}

130
131
		pCore->Initialize();

132
133
134
135
136
137
138
139
140

		// Server
		pServer = IVANetServer::Create();
		std::string sServer;

		// Set up the network connection
		int iPort;
		SplitServerString( sServerAddress, sServer, iPort );

141
		pServer->SetCoreInstance( pCore );
142

143
144
		if( ( ec = pServer->Initialize( sServer, iPort ) ) != 0 )
		{
145
			cerr << "[ VAServer  ][Error ] Failed to initialize network communication (errorcode " << ec << ")" << endl;
146
147
148
			return ec;
		}

149
150
		CVACoreVersionInfo ver;
		pCore->GetVersionInfo( &ver );
151

152
153
154
155
156
157
158
159
160
161
162
		cout << endl << "[ VAServer  ] Core version: " << ver.ToString() << endl;
		cout << "[ VAServer  ] Successfully started and listening on " << sServer << ":" << iPort << endl << endl;
		cout << "[ VAServer  ] Controls:\n" <<
			"[ VAServer  ]    m    Toggle output muting" << endl <<
			"[ VAServer  ]    +    Increase output gain by 3dB" << endl <<
			"[ VAServer  ]    0    Output gain 0dB" << endl <<
			"[ VAServer  ]    -    Decrease output gain by 3dB" << endl <<
			"[ VAServer  ]    r    Reset core" << endl <<
			"[ VAServer  ]    l    Circulate log levels" << endl <<
			"[ VAServer  ]    c    List connected clients" << endl <<
			"[ VAServer  ]    q    Quit" << endl << endl;
163
164
165
166

		while( true )
		{
			const int CTRL_D = 4;
167
			int c = getch();
168
169
170
171
172
173

			if( c == CTRL_D || c == 'q' ) break;

			if( ( char ) c == 'm' )
			{
				bool bMuted = pServer->GetCoreInstance()->IsOutputMuted();
174
				cout << "[ VAServer  ] " << ( !bMuted ? "Muting" : "Unmuting" ) << " global output" << endl;
175
176
177
178
179
				pServer->GetCoreInstance()->SetOutputMuted( !bMuted );
			}

			if( ( char ) c == '0' )
			{
180
				cout << "[ VAServer  ] Setting output gain to 0 dB" << endl;
181
182
183
184
185
186
187
				pServer->GetCoreInstance()->SetOutputGain( 1.0 );
			}

			if( ( char ) c == '+' )
			{
				double dGain = pServer->GetCoreInstance()->GetOutputGain();
				dGain *= 1.4125;
188
				cout << "[ VAServer  ] Setting output gain to " << ratio_to_db20_str( dGain ) << endl;
189
190
191
192
193
194
195
				pServer->GetCoreInstance()->SetOutputGain( dGain );
			}

			if( ( char ) c == '-' )
			{
				double dGain = pServer->GetCoreInstance()->GetOutputGain();
				dGain /= 1.4125;
196
				cout << "[ VAServer  ] Setting output gain to " << ratio_to_db20_str( dGain ) << endl;
197
198
199
200
201
202
				pServer->GetCoreInstance()->SetOutputGain( dGain );
			}

			if( ( char ) c == 'l' )
			{
				CVAStruct oArgs, oReturn, oNewArgs;
203
				oArgs[ "command" ] = "get";
204
205
				oArgs[ std::string( "debug" ) ] = CVAStruct();
				oArgs[ std::string( "debug" ) ][ std::string( "loglevel" ) ] = true;
206
				pServer->GetCoreInstance()->CallModule( "VACore", oArgs, oReturn );
207
				int iCurrentLogLevel = oReturn[ std::string( "debug" ) ][ std::string( "loglevel" ) ];
208
				int iNewLogLevel = int( iCurrentLogLevel + 1 ) % 6;
209
210
				oNewArgs[ "command" ] = "set";
				oNewArgs[ "debug" ] = CVAStruct();
211
				oNewArgs[ std::string( "debug" ) ][ std::string( "loglevel" ) ] = iNewLogLevel;
212
				pServer->GetCoreInstance()->CallModule( "VACore", oNewArgs, oReturn );
213
214

				cout << "[ VAServer  ] Switched to log level: " << IVACore::GetLogLevelStr( iNewLogLevel ) << endl;
215
216
217
218
			}

			if( ( char ) c == 'r' )
			{
219
				cout << "[ VAServer  ] Resetting server manually" << endl;
220
221
				pServer->GetCoreInstance()->Reset();
			}
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241

			if( ( char ) c == 'c' )
			{
				if( !pServer->IsClientConnected() )
				{
					cout << "[ VAServer  ] Nothing yet, still waiting for connections" << endl;
				}
				else
				{
					const int iNumClients = pServer->GetNumConnectedClients();
					if( iNumClients == 1 )
						cout << "[ VAServer  ] One client connected" << endl;
					else
						cout << "[ VAServer  ] Counting " << iNumClients << " connections" << endl;
					for( int i = 0; i < iNumClients; i++ )
					{
						cout << "[ VAServer  ]    +    " << pServer->GetClientHostname( i ) << endl;
					}
				}
			}
242
243
244
245
246
247
248
		}

		delete pServer;
		pCore->Finalize();
		delete pCore;

	}
249
	catch( CVAException& e )
250
	{
251
		cerr << "[ VAServer  ][ Error ] " << e << endl;
252
253
254
255
256
257
258
259
260
261
262

		delete pServer;
		if( pCore )
			pCore->Finalize();
		delete pCore;

		return 255;
	}
	catch( ... )
	{
		delete pServer;
263
		if( pCore )
264
265
266
			pCore->Finalize();
		delete pCore;

267
		cerr << "[ VAServer  ][ Error ] An unknown error occured" << endl;
268
269
270
271
272
		return 255;
	}

	return 0;
}