diff --git a/src/audiomixerboard.cpp b/src/audiomixerboard.cpp index 63247980..47d7f6dc 100755 --- a/src/audiomixerboard.cpp +++ b/src/audiomixerboard.cpp @@ -103,8 +103,12 @@ void CChannelFader::SetGUIDesign ( const EGUIDesign eNewDesign ) case GD_ORIGINAL: // fader pFader->setStyleSheet ( - "QSlider { background-image: url(:/png/fader/res/faderbackground.png);" - " width: 45px; }" + "QSlider { border-image: url(:/png/fader/res/faderbackground.png) 4px 4px 0px 0px;" + " border-top: 4px transparent;" + " border-bottom: 4px transparent;" + " border-left: 0px transparent;" + " border-right: 0px transparent;" + " width: 39px; }" "QSlider::groove { image: url(); }" "QSlider::handle { image: url(:/png/fader/res/faderhandle.png); }" ); diff --git a/src/channel.cpp b/src/channel.cpp index b4c6378b..f3d78acd 100755 --- a/src/channel.cpp +++ b/src/channel.cpp @@ -1,521 +1,521 @@ -/******************************************************************************\ - * Copyright (c) 2004-2009 - * - * 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 "channel.h" - - -/* Implementation *************************************************************/ -CChannel::CChannel ( const bool bNIsServer ) : - bIsServer ( bNIsServer ), - sName ( "" ), - vecdGains ( USED_NUM_CHANNELS, (double) 1.0 ), - bIsEnabled ( false ), - iNetwFrameSizeFact ( FRAME_SIZE_FACTOR_DEFAULT ), - iNetwFrameSize ( 20 ) // must be > 0 and should be close to a valid size -{ - // initial value for connection time out counter, we calculate the total - // number of samples here and subtract the number of samples of the block - // which we take out of the buffer to be independent of block sizes - iConTimeOutStartVal = CON_TIME_OUT_SEC_MAX * SYSTEM_SAMPLE_RATE; - - // init time-out for the buffer with zero -> no connection - iConTimeOut = 0; - - // init the socket buffer - SetSockBufNumFrames ( DEF_NET_BUF_SIZE_NUM_BL ); - - // initialize cycle time variance measurement with defaults - CycleTimeVariance.Init ( SYSTEM_FRAME_SIZE_SAMPLES, - SYSTEM_SAMPLE_RATE, TIME_MOV_AV_RESPONSE ); - - - // connections ------------------------------------------------------------- - QObject::connect ( &Protocol, - SIGNAL ( MessReadyForSending ( CVector ) ), - this, SLOT ( OnSendProtMessage ( CVector ) ) ); - - QObject::connect ( &Protocol, - SIGNAL ( ChangeJittBufSize ( int ) ), - this, SLOT ( OnJittBufSizeChange ( int ) ) ); - - QObject::connect ( &Protocol, - SIGNAL ( ReqJittBufSize() ), - SIGNAL ( ReqJittBufSize() ) ); - - QObject::connect ( &Protocol, - SIGNAL ( ReqChanName() ), - SIGNAL ( ReqChanName() ) ); - - QObject::connect ( &Protocol, - SIGNAL ( ReqConnClientsList() ), - SIGNAL ( ReqConnClientsList() ) ); - - QObject::connect ( &Protocol, - SIGNAL ( ConClientListMesReceived ( CVector ) ), - SIGNAL ( ConClientListMesReceived ( CVector ) ) ); - - QObject::connect( &Protocol, SIGNAL ( ChangeChanGain ( int, double ) ), - this, SLOT ( OnChangeChanGain ( int, double ) ) ); - - QObject::connect( &Protocol, SIGNAL ( ChangeChanName ( QString ) ), - this, SLOT ( OnChangeChanName ( QString ) ) ); - - QObject::connect( &Protocol, SIGNAL ( ChatTextReceived ( QString ) ), - this, SIGNAL ( ChatTextReceived ( QString ) ) ); - - QObject::connect( &Protocol, SIGNAL ( PingReceived ( int ) ), - this, SIGNAL ( PingReceived ( int ) ) ); - - QObject::connect ( &Protocol, - SIGNAL ( NetTranspPropsReceived ( CNetworkTransportProps ) ), - this, SLOT ( OnNetTranspPropsReceived ( CNetworkTransportProps ) ) ); - - QObject::connect ( &Protocol, - SIGNAL ( ReqNetTranspProps() ), - this, SLOT ( OnReqNetTranspProps() ) ); - - QObject::connect ( &Protocol, SIGNAL ( Disconnection() ), - this, SLOT ( OnDisconnection() ) ); -} - -bool CChannel::ProtocolIsEnabled() -{ - // for the server, only enable protocol if the channel is connected, i.e., - // successfully audio packets are received from a client - // for the client, enable protocol if the channel is enabled, i.e., the - // connection button was hit by the user - if ( bIsServer ) - { - return IsConnected(); - } - else - { - return bIsEnabled; - } -} - -void CChannel::SetEnable ( const bool bNEnStat ) -{ - QMutexLocker locker ( &Mutex ); - - // set internal parameter - bIsEnabled = bNEnStat; - - // if channel is not enabled, reset time out count and protocol - if ( !bNEnStat ) - { - iConTimeOut = 0; - Protocol.Reset(); - } -} - -void CChannel::SetNetwFrameSizeAndFact ( const int iNewNetwFrameSize, - const int iNewNetwFrameSizeFact ) -{ - // this function is intended for the server (not the client) - QMutexLocker locker ( &Mutex ); - - // store new values - iNetwFrameSize = iNewNetwFrameSize; - iNetwFrameSizeFact = iNewNetwFrameSizeFact; - - // init socket buffer - SockBuf.Init ( iNetwFrameSize, iCurSockBufNumFrames ); - - // init conversion buffer - ConvBuf.Init ( iNetwFrameSize * iNetwFrameSizeFact ); - - // initialize and reset cycle time variance measurement - CycleTimeVariance.Init ( iNetwFrameSizeFact * SYSTEM_FRAME_SIZE_SAMPLES, - SYSTEM_SAMPLE_RATE, TIME_MOV_AV_RESPONSE ); - - CycleTimeVariance.Reset(); - - // tell the server that audio coding has changed - CreateNetTranspPropsMessFromCurrentSettings(); -} - -bool CChannel::SetSockBufNumFrames ( const int iNewNumFrames ) -{ - QMutexLocker locker ( &Mutex ); // this opperation must be done with mutex - - // first check for valid input parameter range - if ( ( iNewNumFrames >= MIN_NET_BUF_SIZE_NUM_BL ) && - ( iNewNumFrames <= MAX_NET_BUF_SIZE_NUM_BL ) ) - { - // store new value - iCurSockBufNumFrames = iNewNumFrames; - - // the network block size is a multiple of the minimum network - // block size - SockBuf.Init ( iNetwFrameSize, iNewNumFrames ); - - return false; // -> no error - } - - return true; // set error flag -} - -void CChannel::SetGain ( const int iChanID, const double dNewGain ) -{ - QMutexLocker locker ( &Mutex ); - - // set value (make sure channel ID is in range) - if ( ( iChanID >= 0 ) && ( iChanID < USED_NUM_CHANNELS ) ) - { - vecdGains[iChanID] = dNewGain; - } -} - -double CChannel::GetGain ( const int iChanID ) -{ - QMutexLocker locker ( &Mutex ); - - // get value (make sure channel ID is in range) - if ( ( iChanID >= 0 ) && ( iChanID < USED_NUM_CHANNELS ) ) - { - return vecdGains[iChanID]; - } - else - { - return 0; - } -} - -void CChannel::SetName ( const QString strNewName ) -{ - bool bNameHasChanged = false; - - Mutex.lock(); - { - // apply value (if different from previous name) - if ( sName.compare ( strNewName ) ) - { - sName = strNewName; - bNameHasChanged = true; - } - } - Mutex.unlock(); - - // fire message that name has changed - if ( bNameHasChanged ) - { - // the "emit" has to be done outside the mutexed region - emit NameHasChanged(); - } -} -QString CChannel::GetName() -{ - // make sure the string is not written at the same time when it is - // read here -> use mutex to secure access - QMutexLocker locker ( &Mutex ); - - return sName; -} - -void CChannel::OnSendProtMessage ( CVector vecMessage ) -{ - // only send messages if protocol is enabled, otherwise delete complete - // queue - if ( ProtocolIsEnabled() ) - { - // emit message to actually send the data - emit MessReadyForSending ( vecMessage ); - } - else - { - // delete send message queue - Protocol.Reset(); - } -} - -void CChannel::OnJittBufSizeChange ( int iNewJitBufSize ) -{ - SetSockBufNumFrames ( iNewJitBufSize ); -} - -void CChannel::OnChangeChanGain ( int iChanID, double dNewGain ) -{ - SetGain ( iChanID, dNewGain ); -} - -void CChannel::OnChangeChanName ( QString strName ) -{ - SetName ( strName ); -} - -bool CChannel::GetAddress ( CHostAddress& RetAddr ) -{ - QMutexLocker locker ( &Mutex ); - - if ( IsConnected() ) - { - RetAddr = InetAddr; - return true; - } - else - { - RetAddr = CHostAddress(); - return false; - } -} - -void CChannel::OnNetTranspPropsReceived ( CNetworkTransportProps NetworkTransportProps ) -{ - // only the server shall act on network transport properties message - if ( bIsServer ) - { - QMutexLocker locker ( &Mutex ); - - // store received parameters - iNetwFrameSizeFact = NetworkTransportProps.iBlockSizeFact; - iNetwFrameSize = - NetworkTransportProps.iBaseNetworkPacketSize; - - // update socket buffer (the network block size is a multiple of the - // minimum network frame size - SockBuf.Init ( iNetwFrameSize, iCurSockBufNumFrames ); - - // init conversion buffer - ConvBuf.Init ( iNetwFrameSize * iNetwFrameSizeFact ); - } -} - -void CChannel::OnReqNetTranspProps() -{ - CreateNetTranspPropsMessFromCurrentSettings(); -} - -void CChannel::CreateNetTranspPropsMessFromCurrentSettings() -{ - CNetworkTransportProps NetworkTransportProps ( - iNetwFrameSize, - iNetwFrameSizeFact, - 1, // right now we only use mono - SYSTEM_SAMPLE_RATE, - CT_CELT, // always CELT coding - 0, - 0 ); - - // send current network transport properties - Protocol.CreateNetwTranspPropsMes ( NetworkTransportProps ); -} - -void CChannel::OnDisconnection() -{ - // set time out counter to a small value > 0 so that the next time a - // received audio block is queried, the disconnection is performed - // (assuming that no audio packet is received in the meantime) - iConTimeOut = 1; // a small number > 0 -} - -EPutDataStat CChannel::PutData ( const CVector& vecbyData, - int iNumBytes ) -{ - EPutDataStat eRet = PS_GEN_ERROR; - - // init flags - bool bIsProtocolPacket = false; - bool bIsAudioPacket = false; - bool bNewConnection = false; - - if ( bIsEnabled ) - { - // first check if this is protocol data - // only use protocol data if protocol mechanism is enabled - if ( ProtocolIsEnabled() ) - { - // parse the message assuming this is a protocol message - if ( !Protocol.ParseMessage ( vecbyData, iNumBytes ) ) - { - // set status flags - eRet = PS_PROT_OK; - bIsProtocolPacket = true; - } - } - - // only try to parse audio if it was not a protocol packet - if ( !bIsProtocolPacket ) - { - Mutex.lock(); - { - - -// TODO only process data if network properties protocol message has been arrived - - - // only process audio if packet has correct size - if ( iNumBytes == ( iNetwFrameSize * iNetwFrameSizeFact ) ) - { - // set audio packet flag - bIsAudioPacket = true; - - // store new packet in jitter buffer - if ( SockBuf.Put ( vecbyData, iNumBytes ) ) - { - eRet = PS_AUDIO_OK; - } - else - { - eRet = PS_AUDIO_ERR; - } - - // update cycle time variance measurement (this is only - // used by the client so do not update for server channel) - if ( !bIsServer ) - { - CycleTimeVariance.Update(); - } - } - else - { - // the protocol parsing failed and this was no audio block, - // we treat this as protocol error (unkown packet) - eRet = PS_PROT_ERR; - } - - // all network packets except of valid llcon protocol messages - // regardless if they are valid or invalid audio packets lead to - // a state change to a connected channel - // this is because protocol messages can only be sent on a - // connected channel and the client has to inform the server - // about the audio packet properties via the protocol - - // check if channel was not connected, this is a new connection - bNewConnection = !IsConnected(); - - // reset time-out counter - ResetTimeOutCounter(); - } - Mutex.unlock(); - } - - if ( bNewConnection ) - { - // if this is a new connection and the current network packet is - // neither an audio or protocol packet, we have to query the - // network transport properties for the audio packets - // (this is only required for server since we defined that the - // server has to send with the same properties as sent by - // the client) - if ( bIsServer && ( !bIsProtocolPacket ) && ( !bIsAudioPacket ) ) - { - Protocol.CreateReqNetwTranspPropsMes(); - } - - // reset cycle time variance measurement - CycleTimeVariance.Reset(); - - // inform other objects that new connection was established - emit NewConnection(); - } - } - - return eRet; -} - -EGetDataStat CChannel::GetData ( CVector& vecbyData ) -{ - QMutexLocker locker ( &Mutex ); - - EGetDataStat eGetStatus; - - const bool bSockBufState = SockBuf.Get ( vecbyData ); - - // decrease time-out counter - if ( iConTimeOut > 0 ) - { - // subtract the number of samples of the current block since the - // time out counter is based on samples not on blocks (definition: - // always one atomic block is get by using the GetData() function - // where the atomic block size is "SYSTEM_FRAME_SIZE_SAMPLES") - -// TODO this code only works with the above assumption -> better -// implementation so that we are not depending on assumptions - - iConTimeOut -= SYSTEM_FRAME_SIZE_SAMPLES; - - if ( iConTimeOut <= 0 ) - { - // channel is just disconnected - eGetStatus = GS_CHAN_NOW_DISCONNECTED; - iConTimeOut = 0; // make sure we do not have negative values - - // emit message - emit Disconnected(); - } - else - { - if ( bSockBufState ) - { - // everything is ok - eGetStatus = GS_BUFFER_OK; - } - else - { - // channel is not yet disconnected but no data in buffer - eGetStatus = GS_BUFFER_UNDERRUN; - } - } - } - else - { - // channel is disconnected - eGetStatus = GS_CHAN_NOT_CONNECTED; - } - - return eGetStatus; -} - -CVector CChannel::PrepSendPacket ( const CVector& vecbyNPacket ) -{ - QMutexLocker locker ( &Mutex ); - - // if the block is not ready we have to initialize with zero length to - // tell the following network send routine that nothing should be sent - CVector vecbySendBuf ( 0 ); - - // use conversion buffer to convert sound card block size in network - // block size - if ( ConvBuf.Put ( vecbyNPacket ) ) - { - // a packet is ready - vecbySendBuf.Init ( iNetwFrameSize * iNetwFrameSizeFact ); - vecbySendBuf = ConvBuf.Get(); - } - - return vecbySendBuf; -} - -int CChannel::GetUploadRateKbps() -{ - const int iAudioSizeOut = iNetwFrameSizeFact * SYSTEM_FRAME_SIZE_SAMPLES; - - // we assume that the UDP packet which is transported via IP has an - // additional header size of - // 8 (UDP) + 20 (IP without optional fields) = 28 bytes - return ( iNetwFrameSize * iNetwFrameSizeFact + 28 /* header */ ) * - 8 /* bits per byte */ * - SYSTEM_SAMPLE_RATE / iAudioSizeOut / 1000; -} +/******************************************************************************\ + * Copyright (c) 2004-2009 + * + * 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 "channel.h" + + +/* Implementation *************************************************************/ +CChannel::CChannel ( const bool bNIsServer ) : + bIsServer ( bNIsServer ), + sName ( "" ), + vecdGains ( USED_NUM_CHANNELS, (double) 1.0 ), + bIsEnabled ( false ), + iNetwFrameSizeFact ( FRAME_SIZE_FACTOR_DEFAULT ), + iNetwFrameSize ( 20 ) // must be > 0 and should be close to a valid size +{ + // initial value for connection time out counter, we calculate the total + // number of samples here and subtract the number of samples of the block + // which we take out of the buffer to be independent of block sizes + iConTimeOutStartVal = CON_TIME_OUT_SEC_MAX * SYSTEM_SAMPLE_RATE; + + // init time-out for the buffer with zero -> no connection + iConTimeOut = 0; + + // init the socket buffer + SetSockBufNumFrames ( DEF_NET_BUF_SIZE_NUM_BL ); + + // initialize cycle time variance measurement with defaults + CycleTimeVariance.Init ( SYSTEM_FRAME_SIZE_SAMPLES, + SYSTEM_SAMPLE_RATE, TIME_MOV_AV_RESPONSE ); + + + // connections ------------------------------------------------------------- + QObject::connect ( &Protocol, + SIGNAL ( MessReadyForSending ( CVector ) ), + this, SLOT ( OnSendProtMessage ( CVector ) ) ); + + QObject::connect ( &Protocol, + SIGNAL ( ChangeJittBufSize ( int ) ), + this, SLOT ( OnJittBufSizeChange ( int ) ) ); + + QObject::connect ( &Protocol, + SIGNAL ( ReqJittBufSize() ), + SIGNAL ( ReqJittBufSize() ) ); + + QObject::connect ( &Protocol, + SIGNAL ( ReqChanName() ), + SIGNAL ( ReqChanName() ) ); + + QObject::connect ( &Protocol, + SIGNAL ( ReqConnClientsList() ), + SIGNAL ( ReqConnClientsList() ) ); + + QObject::connect ( &Protocol, + SIGNAL ( ConClientListMesReceived ( CVector ) ), + SIGNAL ( ConClientListMesReceived ( CVector ) ) ); + + QObject::connect( &Protocol, SIGNAL ( ChangeChanGain ( int, double ) ), + this, SLOT ( OnChangeChanGain ( int, double ) ) ); + + QObject::connect( &Protocol, SIGNAL ( ChangeChanName ( QString ) ), + this, SLOT ( OnChangeChanName ( QString ) ) ); + + QObject::connect( &Protocol, SIGNAL ( ChatTextReceived ( QString ) ), + this, SIGNAL ( ChatTextReceived ( QString ) ) ); + + QObject::connect( &Protocol, SIGNAL ( PingReceived ( int ) ), + this, SIGNAL ( PingReceived ( int ) ) ); + + QObject::connect ( &Protocol, + SIGNAL ( NetTranspPropsReceived ( CNetworkTransportProps ) ), + this, SLOT ( OnNetTranspPropsReceived ( CNetworkTransportProps ) ) ); + + QObject::connect ( &Protocol, + SIGNAL ( ReqNetTranspProps() ), + this, SLOT ( OnReqNetTranspProps() ) ); + + QObject::connect ( &Protocol, SIGNAL ( Disconnection() ), + this, SLOT ( OnDisconnection() ) ); +} + +bool CChannel::ProtocolIsEnabled() +{ + // for the server, only enable protocol if the channel is connected, i.e., + // successfully audio packets are received from a client + // for the client, enable protocol if the channel is enabled, i.e., the + // connection button was hit by the user + if ( bIsServer ) + { + return IsConnected(); + } + else + { + return bIsEnabled; + } +} + +void CChannel::SetEnable ( const bool bNEnStat ) +{ + QMutexLocker locker ( &Mutex ); + + // set internal parameter + bIsEnabled = bNEnStat; + + // if channel is not enabled, reset time out count and protocol + if ( !bNEnStat ) + { + iConTimeOut = 0; + Protocol.Reset(); + } +} + +void CChannel::SetNetwFrameSizeAndFact ( const int iNewNetwFrameSize, + const int iNewNetwFrameSizeFact ) +{ + // this function is intended for the server (not the client) + QMutexLocker locker ( &Mutex ); + + // store new values + iNetwFrameSize = iNewNetwFrameSize; + iNetwFrameSizeFact = iNewNetwFrameSizeFact; + + // init socket buffer + SockBuf.Init ( iNetwFrameSize, iCurSockBufNumFrames ); + + // init conversion buffer + ConvBuf.Init ( iNetwFrameSize * iNetwFrameSizeFact ); + + // initialize and reset cycle time variance measurement + CycleTimeVariance.Init ( iNetwFrameSizeFact * SYSTEM_FRAME_SIZE_SAMPLES, + SYSTEM_SAMPLE_RATE, TIME_MOV_AV_RESPONSE ); + + CycleTimeVariance.Reset(); + + // tell the server that audio coding has changed + CreateNetTranspPropsMessFromCurrentSettings(); +} + +bool CChannel::SetSockBufNumFrames ( const int iNewNumFrames ) +{ + QMutexLocker locker ( &Mutex ); // this opperation must be done with mutex + + // first check for valid input parameter range + if ( ( iNewNumFrames >= MIN_NET_BUF_SIZE_NUM_BL ) && + ( iNewNumFrames <= MAX_NET_BUF_SIZE_NUM_BL ) ) + { + // store new value + iCurSockBufNumFrames = iNewNumFrames; + + // the network block size is a multiple of the minimum network + // block size + SockBuf.Init ( iNetwFrameSize, iNewNumFrames ); + + return false; // -> no error + } + + return true; // set error flag +} + +void CChannel::SetGain ( const int iChanID, const double dNewGain ) +{ + QMutexLocker locker ( &Mutex ); + + // set value (make sure channel ID is in range) + if ( ( iChanID >= 0 ) && ( iChanID < USED_NUM_CHANNELS ) ) + { + vecdGains[iChanID] = dNewGain; + } +} + +double CChannel::GetGain ( const int iChanID ) +{ + QMutexLocker locker ( &Mutex ); + + // get value (make sure channel ID is in range) + if ( ( iChanID >= 0 ) && ( iChanID < USED_NUM_CHANNELS ) ) + { + return vecdGains[iChanID]; + } + else + { + return 0; + } +} + +void CChannel::SetName ( const QString strNewName ) +{ + bool bNameHasChanged = false; + + Mutex.lock(); + { + // apply value (if different from previous name) + if ( sName.compare ( strNewName ) ) + { + sName = strNewName; + bNameHasChanged = true; + } + } + Mutex.unlock(); + + // fire message that name has changed + if ( bNameHasChanged ) + { + // the "emit" has to be done outside the mutexed region + emit NameHasChanged(); + } +} +QString CChannel::GetName() +{ + // make sure the string is not written at the same time when it is + // read here -> use mutex to secure access + QMutexLocker locker ( &Mutex ); + + return sName; +} + +void CChannel::OnSendProtMessage ( CVector vecMessage ) +{ + // only send messages if protocol is enabled, otherwise delete complete + // queue + if ( ProtocolIsEnabled() ) + { + // emit message to actually send the data + emit MessReadyForSending ( vecMessage ); + } + else + { + // delete send message queue + Protocol.Reset(); + } +} + +void CChannel::OnJittBufSizeChange ( int iNewJitBufSize ) +{ + SetSockBufNumFrames ( iNewJitBufSize ); +} + +void CChannel::OnChangeChanGain ( int iChanID, double dNewGain ) +{ + SetGain ( iChanID, dNewGain ); +} + +void CChannel::OnChangeChanName ( QString strName ) +{ + SetName ( strName ); +} + +bool CChannel::GetAddress ( CHostAddress& RetAddr ) +{ + QMutexLocker locker ( &Mutex ); + + if ( IsConnected() ) + { + RetAddr = InetAddr; + return true; + } + else + { + RetAddr = CHostAddress(); + return false; + } +} + +void CChannel::OnNetTranspPropsReceived ( CNetworkTransportProps NetworkTransportProps ) +{ + // only the server shall act on network transport properties message + if ( bIsServer ) + { + QMutexLocker locker ( &Mutex ); + + // store received parameters + iNetwFrameSizeFact = NetworkTransportProps.iBlockSizeFact; + iNetwFrameSize = + NetworkTransportProps.iBaseNetworkPacketSize; + + // update socket buffer (the network block size is a multiple of the + // minimum network frame size + SockBuf.Init ( iNetwFrameSize, iCurSockBufNumFrames ); + + // init conversion buffer + ConvBuf.Init ( iNetwFrameSize * iNetwFrameSizeFact ); + } +} + +void CChannel::OnReqNetTranspProps() +{ + CreateNetTranspPropsMessFromCurrentSettings(); +} + +void CChannel::CreateNetTranspPropsMessFromCurrentSettings() +{ + CNetworkTransportProps NetworkTransportProps ( + iNetwFrameSize, + iNetwFrameSizeFact, + 1, // right now we only use mono + SYSTEM_SAMPLE_RATE, + CT_CELT, // always CELT coding + 0, + 0 ); + + // send current network transport properties + Protocol.CreateNetwTranspPropsMes ( NetworkTransportProps ); +} + +void CChannel::OnDisconnection() +{ + // set time out counter to a small value > 0 so that the next time a + // received audio block is queried, the disconnection is performed + // (assuming that no audio packet is received in the meantime) + iConTimeOut = 1; // a small number > 0 +} + +EPutDataStat CChannel::PutData ( const CVector& vecbyData, + int iNumBytes ) +{ + EPutDataStat eRet = PS_GEN_ERROR; + + // init flags + bool bIsProtocolPacket = false; + bool bIsAudioPacket = false; + bool bNewConnection = false; + + if ( bIsEnabled ) + { + // first check if this is protocol data + // only use protocol data if protocol mechanism is enabled + if ( ProtocolIsEnabled() ) + { + // parse the message assuming this is a protocol message + if ( !Protocol.ParseMessage ( vecbyData, iNumBytes ) ) + { + // set status flags + eRet = PS_PROT_OK; + bIsProtocolPacket = true; + } + } + + // only try to parse audio if it was not a protocol packet + if ( !bIsProtocolPacket ) + { + Mutex.lock(); + { + + +// TODO only process data if network properties protocol message has been arrived + + + // only process audio if packet has correct size + if ( iNumBytes == ( iNetwFrameSize * iNetwFrameSizeFact ) ) + { + // set audio packet flag + bIsAudioPacket = true; + + // store new packet in jitter buffer + if ( SockBuf.Put ( vecbyData, iNumBytes ) ) + { + eRet = PS_AUDIO_OK; + } + else + { + eRet = PS_AUDIO_ERR; + } + + // update cycle time variance measurement (this is only + // used by the client so do not update for server channel) + if ( !bIsServer ) + { + CycleTimeVariance.Update(); + } + } + else + { + // the protocol parsing failed and this was no audio block, + // we treat this as protocol error (unkown packet) + eRet = PS_PROT_ERR; + } + + // all network packets except of valid llcon protocol messages + // regardless if they are valid or invalid audio packets lead to + // a state change to a connected channel + // this is because protocol messages can only be sent on a + // connected channel and the client has to inform the server + // about the audio packet properties via the protocol + + // check if channel was not connected, this is a new connection + bNewConnection = !IsConnected(); + + // reset time-out counter + ResetTimeOutCounter(); + } + Mutex.unlock(); + } + + if ( bNewConnection ) + { + // if this is a new connection and the current network packet is + // neither an audio or protocol packet, we have to query the + // network transport properties for the audio packets + // (this is only required for server since we defined that the + // server has to send with the same properties as sent by + // the client) + if ( bIsServer && ( !bIsProtocolPacket ) && ( !bIsAudioPacket ) ) + { + Protocol.CreateReqNetwTranspPropsMes(); + } + + // reset cycle time variance measurement + CycleTimeVariance.Reset(); + + // inform other objects that new connection was established + emit NewConnection(); + } + } + + return eRet; +} + +EGetDataStat CChannel::GetData ( CVector& vecbyData ) +{ + QMutexLocker locker ( &Mutex ); + + EGetDataStat eGetStatus; + + const bool bSockBufState = SockBuf.Get ( vecbyData ); + + // decrease time-out counter + if ( iConTimeOut > 0 ) + { + // subtract the number of samples of the current block since the + // time out counter is based on samples not on blocks (definition: + // always one atomic block is get by using the GetData() function + // where the atomic block size is "SYSTEM_FRAME_SIZE_SAMPLES") + +// TODO this code only works with the above assumption -> better +// implementation so that we are not depending on assumptions + + iConTimeOut -= SYSTEM_FRAME_SIZE_SAMPLES; + + if ( iConTimeOut <= 0 ) + { + // channel is just disconnected + eGetStatus = GS_CHAN_NOW_DISCONNECTED; + iConTimeOut = 0; // make sure we do not have negative values + + // emit message + emit Disconnected(); + } + else + { + if ( bSockBufState ) + { + // everything is ok + eGetStatus = GS_BUFFER_OK; + } + else + { + // channel is not yet disconnected but no data in buffer + eGetStatus = GS_BUFFER_UNDERRUN; + } + } + } + else + { + // channel is disconnected + eGetStatus = GS_CHAN_NOT_CONNECTED; + } + + return eGetStatus; +} + +CVector CChannel::PrepSendPacket ( const CVector& vecbyNPacket ) +{ + QMutexLocker locker ( &Mutex ); + + // if the block is not ready we have to initialize with zero length to + // tell the following network send routine that nothing should be sent + CVector vecbySendBuf ( 0 ); + + // use conversion buffer to convert sound card block size in network + // block size + if ( ConvBuf.Put ( vecbyNPacket ) ) + { + // a packet is ready + vecbySendBuf.Init ( iNetwFrameSize * iNetwFrameSizeFact ); + vecbySendBuf = ConvBuf.Get(); + } + + return vecbySendBuf; +} + +int CChannel::GetUploadRateKbps() +{ + const int iAudioSizeOut = iNetwFrameSizeFact * SYSTEM_FRAME_SIZE_SAMPLES; + + // we assume that the UDP packet which is transported via IP has an + // additional header size of + // 8 (UDP) + 20 (IP without optional fields) = 28 bytes + return ( iNetwFrameSize * iNetwFrameSizeFact + 28 /* header */ ) * + 8 /* bits per byte */ * + SYSTEM_SAMPLE_RATE / iAudioSizeOut / 1000; +} diff --git a/src/res/faderbackground.png b/src/res/faderbackground.png index 5c3c56ce..36bd9962 100755 Binary files a/src/res/faderbackground.png and b/src/res/faderbackground.png differ diff --git a/src/util.h b/src/util.h index eb234e12..9733106e 100755 --- a/src/util.h +++ b/src/util.h @@ -598,7 +598,7 @@ public: RespTimeMoAvBuf.Reset(); } - void Update() + double Update() { // add time difference const int CurTime = PreciseTime.elapsed(); @@ -625,6 +625,8 @@ public: // store old time value TimeLastBlock = CurTime; + + return dCurAddVal; } // return the standard deviation, for that we need to calculate