2006-01-28 12:29:22 +01:00
|
|
|
/******************************************************************************\
|
|
|
|
* Copyright (c) 2004-2006
|
|
|
|
*
|
|
|
|
* Author(s):
|
|
|
|
* Volker Fischer
|
|
|
|
*
|
|
|
|
******************************************************************************
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify it under
|
|
|
|
* the terms of the GNU General Public License as published by the Free Software
|
|
|
|
* Foundation; either version 2 of the License, or (at your option) any later
|
|
|
|
* version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
|
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
|
|
* details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along with
|
|
|
|
* this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*
|
|
|
|
\******************************************************************************/
|
|
|
|
|
|
|
|
#include "server.h"
|
|
|
|
|
|
|
|
|
|
|
|
/* Implementation *************************************************************/
|
2006-02-18 13:01:29 +01:00
|
|
|
CServer::CServer () : Socket ( &ChannelSet, this )
|
2006-01-28 12:29:22 +01:00
|
|
|
{
|
2006-02-17 22:08:05 +01:00
|
|
|
vecsSendData.Init ( MIN_BLOCK_SIZE_SAMPLES );
|
2006-01-28 12:29:22 +01:00
|
|
|
|
|
|
|
/* init moving average buffer for response time evaluation */
|
2006-02-17 22:08:05 +01:00
|
|
|
RespTimeMoAvBuf.Init ( LEN_MOV_AV_RESPONSE );
|
2006-01-28 12:29:22 +01:00
|
|
|
|
|
|
|
/* connect timer timeout signal */
|
2006-02-17 22:08:05 +01:00
|
|
|
QObject::connect ( &Timer, SIGNAL ( timeout () ),
|
2006-02-20 22:09:36 +01:00
|
|
|
this, SLOT ( OnTimer () ) );
|
|
|
|
|
2006-03-04 12:11:26 +01:00
|
|
|
// connection for protocol
|
|
|
|
QObject::connect ( &ChannelSet,
|
|
|
|
SIGNAL ( MessReadyForSending ( int, CVector<uint8_t> ) ),
|
|
|
|
this, SLOT ( OnSendProtMessage ( int, CVector<uint8_t> ) ) );
|
|
|
|
|
2006-02-20 22:09:36 +01:00
|
|
|
#ifdef _WIN32
|
|
|
|
// event handling of custom events seems not to work under Windows in this
|
|
|
|
// class, do not use automatic start/stop of server in Windows version
|
|
|
|
Start ();
|
|
|
|
#endif
|
2006-03-04 12:11:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void CServer::OnSendProtMessage ( int iChID, CVector<uint8_t> vecMessage )
|
|
|
|
{
|
|
|
|
|
|
|
|
// convert unsigned uint8_t in char, TODO convert all buffers in uint8_t
|
|
|
|
CVector<unsigned char> vecbyDataConv ( vecMessage.Size () );
|
|
|
|
for ( int i = 0; i < vecMessage.Size (); i++ ) {
|
|
|
|
vecbyDataConv[i] = static_cast<unsigned char> ( vecMessage[i] );
|
|
|
|
}
|
|
|
|
|
|
|
|
// the protocol queries me to call the function to send the message
|
|
|
|
// send it through the network
|
|
|
|
Socket.SendPacket ( vecbyDataConv,
|
|
|
|
ChannelSet.GetAddress ( iChID ) );
|
|
|
|
}
|
2006-01-28 12:29:22 +01:00
|
|
|
|
2006-02-17 22:08:05 +01:00
|
|
|
void CServer::Start ()
|
2006-02-12 15:26:46 +01:00
|
|
|
{
|
|
|
|
if ( !IsRunning () )
|
|
|
|
{
|
|
|
|
/* start main timer */
|
2006-02-17 22:08:05 +01:00
|
|
|
Timer.start ( MIN_BLOCK_DURATION_MS );
|
2006-01-28 12:29:22 +01:00
|
|
|
|
2006-02-12 15:26:46 +01:00
|
|
|
/* init time for response time evaluation */
|
2006-02-17 22:08:05 +01:00
|
|
|
TimeLastBlock = QTime::currentTime ();
|
2006-02-18 13:08:56 +01:00
|
|
|
|
2006-02-18 13:19:27 +01:00
|
|
|
qDebug("Server started");
|
2006-02-12 15:26:46 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-02-17 22:08:05 +01:00
|
|
|
void CServer::Stop ()
|
2006-02-12 15:26:46 +01:00
|
|
|
{
|
|
|
|
/* stop main timer */
|
2006-02-17 22:08:05 +01:00
|
|
|
Timer.stop ();
|
2006-02-18 13:19:27 +01:00
|
|
|
|
|
|
|
qDebug("Server stopped");
|
2006-02-12 15:26:46 +01:00
|
|
|
}
|
2006-01-28 12:29:22 +01:00
|
|
|
|
2006-02-17 22:08:05 +01:00
|
|
|
void CServer::OnTimer ()
|
2006-01-28 12:29:22 +01:00
|
|
|
{
|
|
|
|
CVector<int> vecChanID;
|
2006-02-17 22:08:05 +01:00
|
|
|
CVector<CVector<double> > vecvecdData ( MIN_BLOCK_SIZE_SAMPLES );
|
2006-01-28 12:29:22 +01:00
|
|
|
|
|
|
|
/* get data from all connected clients */
|
2006-02-12 15:26:46 +01:00
|
|
|
ChannelSet.GetBlockAllConC ( vecChanID, vecvecdData );
|
|
|
|
const int iNumClients = vecvecdData.Size ();
|
|
|
|
|
|
|
|
/* Check if at least one client is connected. If not, stop server until
|
|
|
|
one client is connected */
|
|
|
|
if ( iNumClients != 0 )
|
2006-01-28 12:29:22 +01:00
|
|
|
{
|
2006-02-12 15:26:46 +01:00
|
|
|
/* actual processing of audio data -> mix */
|
|
|
|
vecsSendData = ProcessData ( vecvecdData );
|
|
|
|
|
|
|
|
/* send the same data to all connected clients */
|
|
|
|
for ( int i = 0; i < iNumClients; i++ )
|
|
|
|
{
|
|
|
|
Socket.SendPacket (
|
|
|
|
ChannelSet.PrepSendPacket ( vecChanID[i], vecsSendData ),
|
2006-02-26 14:27:19 +01:00
|
|
|
ChannelSet.GetAddress ( vecChanID[i] ) );
|
2006-02-12 15:26:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* update response time measurement --------------------------------- */
|
|
|
|
/* add time difference */
|
|
|
|
const QTime CurTime = QTime::currentTime ();
|
2006-01-28 12:29:22 +01:00
|
|
|
|
2006-02-12 15:26:46 +01:00
|
|
|
/* we want to calculate the standard deviation (we assume that the mean
|
|
|
|
is correct at the block period time) */
|
2006-02-17 22:08:05 +01:00
|
|
|
const double dCurAddVal = ( (double) TimeLastBlock.msecsTo ( CurTime ) -
|
|
|
|
MIN_BLOCK_DURATION_MS );
|
2006-01-28 12:29:22 +01:00
|
|
|
|
2006-02-12 15:26:46 +01:00
|
|
|
RespTimeMoAvBuf.Add ( dCurAddVal * dCurAddVal ); /* add squared value */
|
2006-01-28 12:29:22 +01:00
|
|
|
|
2006-02-12 15:26:46 +01:00
|
|
|
/* store old time value */
|
|
|
|
TimeLastBlock = CurTime;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-02-18 13:08:56 +01:00
|
|
|
// Disable server if no clients are connected. In this case the server
|
|
|
|
// does not consume any significant CPU when no client is connected.
|
2006-02-20 22:09:36 +01:00
|
|
|
#ifndef _WIN32
|
|
|
|
// event handling of custom events seems not to work under Windows in this
|
|
|
|
// class, do not use automatic start/stop of server in Windows version
|
2006-02-18 13:08:56 +01:00
|
|
|
Stop ();
|
2006-02-20 22:09:36 +01:00
|
|
|
#endif
|
2006-02-12 15:26:46 +01:00
|
|
|
}
|
2006-01-28 12:29:22 +01:00
|
|
|
}
|
|
|
|
|
2006-02-12 15:26:46 +01:00
|
|
|
CVector<short> CServer::ProcessData ( CVector<CVector<double> >& vecvecdData )
|
2006-01-28 12:29:22 +01:00
|
|
|
{
|
|
|
|
CVector<short> vecsOutData;
|
2006-02-17 22:08:05 +01:00
|
|
|
vecsOutData.Init ( MIN_BLOCK_SIZE_SAMPLES );
|
2006-01-28 12:29:22 +01:00
|
|
|
|
2006-02-12 15:26:46 +01:00
|
|
|
const int iNumClients = vecvecdData.Size ();
|
2006-01-28 12:29:22 +01:00
|
|
|
|
|
|
|
/* we normalize with sqrt() of N to avoid that the level drops too much
|
|
|
|
in case that a new client connects */
|
2006-02-12 15:26:46 +01:00
|
|
|
const double dNorm = sqrt ( (double) iNumClients );
|
2006-01-28 12:29:22 +01:00
|
|
|
|
|
|
|
/* mix all audio data from all clients together */
|
2006-02-17 22:08:05 +01:00
|
|
|
for ( int i = 0; i < MIN_BLOCK_SIZE_SAMPLES; i++ )
|
2006-01-28 12:29:22 +01:00
|
|
|
{
|
|
|
|
double dMixedData = 0.0;
|
|
|
|
|
2006-02-12 15:26:46 +01:00
|
|
|
for ( int j = 0; j < iNumClients; j++ )
|
2006-01-28 12:29:22 +01:00
|
|
|
{
|
|
|
|
dMixedData += vecvecdData[j][i];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* normalization and truncating to short */
|
2006-02-12 15:26:46 +01:00
|
|
|
vecsOutData[i] = Double2Short ( dMixedData / dNorm );
|
2006-01-28 12:29:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return vecsOutData;
|
|
|
|
}
|
2006-02-12 15:26:46 +01:00
|
|
|
|
|
|
|
bool CServer::GetTimingStdDev ( double& dCurTiStdDev )
|
|
|
|
{
|
|
|
|
dCurTiStdDev = 0.0; /* init return value */
|
|
|
|
|
|
|
|
/* only return value if server is active and the actual measurement is
|
|
|
|
updated */
|
|
|
|
if ( IsRunning () )
|
|
|
|
{
|
|
|
|
/* we want to return the standard deviation, for that we need to calculate
|
|
|
|
the sqaure root */
|
|
|
|
dCurTiStdDev = sqrt ( RespTimeMoAvBuf.GetAverage () );
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2006-02-18 13:01:29 +01:00
|
|
|
|
|
|
|
void CServer::customEvent(QCustomEvent* Event)
|
|
|
|
{
|
|
|
|
if (Event->type() == QEvent::User + 11)
|
|
|
|
{
|
|
|
|
const int iMessType = ((CLlconEvent*) Event)->iMessType;
|
|
|
|
|
|
|
|
switch(iMessType)
|
|
|
|
{
|
|
|
|
case MS_PACKET_RECEIVED:
|
2006-02-18 13:08:56 +01:00
|
|
|
// wake up the server if a packet was received
|
|
|
|
// if the server is still running, the call to Start() will have
|
|
|
|
// no effect
|
|
|
|
Start ();
|
2006-02-18 13:01:29 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|