1 /******************************************************************************\
2  * Copyright (c) 2004-2020
3  *
4  * Author(s):
5  *  Volker Fischer
6  *
7  ******************************************************************************
8  *
9  * This program is free software; you can redistribute it and/or modify it under
10  * the terms of the GNU General Public License as published by the Free Software
11  * Foundation; either version 2 of the License, or (at your option) any later
12  * version.
13  *
14  * This program is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17  * details.
18  *
19  * You should have received a copy of the GNU General Public License along with
20  * this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
22  *
23 \******************************************************************************/
24 
25 #include "channel.h"
26 
27 // CChannel implementation *****************************************************
CChannel(const bool bNIsServer)28 CChannel::CChannel ( const bool bNIsServer ) :
29     vecfGains ( MAX_NUM_CHANNELS, 1.0f ),
30     vecfPannings ( MAX_NUM_CHANNELS, 0.5f ),
31     iCurSockBufNumFrames ( INVALID_INDEX ),
32     bDoAutoSockBufSize ( true ),
33     bUseSequenceNumber ( false ), // this is important since in the client we reset on Channel.SetEnable ( false )
34     iSendSequenceNumber ( 0 ),
35     iFadeInCnt ( 0 ),
36     iFadeInCntMax ( FADE_IN_NUM_FRAMES_DBLE_FRAMESIZE ),
37     bIsEnabled ( false ),
38     bIsServer ( bNIsServer ),
39     bIsIdentified ( false ),
40     iAudioFrameSizeSamples ( DOUBLE_SYSTEM_FRAME_SIZE_SAMPLES ),
41     SignalLevelMeter ( false, 0.5 ) // server mode with mono out and faster smoothing
42 {
43     // reset network transport properties
44     ResetNetworkTransportProperties();
45 
46     // initial value for connection time out counter, we calculate the total
47     // number of samples here and subtract the number of samples of the block
48     // which we take out of the buffer to be independent of block sizes
49     iConTimeOutStartVal = CON_TIME_OUT_SEC_MAX * SYSTEM_SAMPLE_RATE_HZ;
50 
51     // init time-out for the buffer with zero -> no connection
52     iConTimeOut = 0;
53 
54     // init the socket buffer
55     SetSockBufNumFrames ( DEF_NET_BUF_SIZE_NUM_BL );
56 
57     // initialize channel info
58     ResetInfo();
59 
60     // Connections -------------------------------------------------------------
61 
62     // clang-format off
63 // TODO if we later do not fire vectors in the emits, we can remove this again
64 qRegisterMetaType<CVector<uint8_t> > ( "CVector<uint8_t>" );
65 qRegisterMetaType<CHostAddress> ( "CHostAddress" );
66     // clang-format on
67 
68     QObject::connect ( &Protocol, &CProtocol::MessReadyForSending, this, &CChannel::OnSendProtMessage );
69 
70     QObject::connect ( &Protocol, &CProtocol::ChangeJittBufSize, this, &CChannel::OnJittBufSizeChange );
71 
72     QObject::connect ( &Protocol, &CProtocol::ReqJittBufSize, this, &CChannel::ReqJittBufSize );
73 
74     QObject::connect ( &Protocol, &CProtocol::ReqChanInfo, this, &CChannel::ReqChanInfo );
75 
76     QObject::connect ( &Protocol, &CProtocol::ReqConnClientsList, this, &CChannel::ReqConnClientsList );
77 
78     QObject::connect ( &Protocol, &CProtocol::ConClientListMesReceived, this, &CChannel::ConClientListMesReceived );
79 
80     QObject::connect ( &Protocol, &CProtocol::ChangeChanGain, this, &CChannel::OnChangeChanGain );
81 
82     QObject::connect ( &Protocol, &CProtocol::ChangeChanPan, this, &CChannel::OnChangeChanPan );
83 
84     QObject::connect ( &Protocol, &CProtocol::ClientIDReceived, this, &CChannel::ClientIDReceived );
85 
86     QObject::connect ( &Protocol, &CProtocol::MuteStateHasChangedReceived, this, &CChannel::MuteStateHasChangedReceived );
87 
88     QObject::connect ( &Protocol, &CProtocol::ChangeChanInfo, this, &CChannel::OnChangeChanInfo );
89 
90     QObject::connect ( &Protocol, &CProtocol::ChatTextReceived, this, &CChannel::ChatTextReceived );
91 
92     QObject::connect ( &Protocol, &CProtocol::NetTranspPropsReceived, this, &CChannel::OnNetTranspPropsReceived );
93 
94     QObject::connect ( &Protocol, &CProtocol::ReqNetTranspProps, this, &CChannel::OnReqNetTranspProps );
95 
96     QObject::connect ( &Protocol, &CProtocol::ReqSplitMessSupport, this, &CChannel::OnReqSplitMessSupport );
97 
98     QObject::connect ( &Protocol, &CProtocol::SplitMessSupported, this, &CChannel::OnSplitMessSupported );
99 
100     QObject::connect ( &Protocol, &CProtocol::LicenceRequired, this, &CChannel::LicenceRequired );
101 
102     QObject::connect ( &Protocol, &CProtocol::VersionAndOSReceived, this, &CChannel::OnVersionAndOSReceived );
103 
104     QObject::connect ( &Protocol, &CProtocol::RecorderStateReceived, this, &CChannel::RecorderStateReceived );
105 }
106 
ProtocolIsEnabled()107 bool CChannel::ProtocolIsEnabled()
108 {
109     // for the server, only enable protocol if the channel is connected, i.e.,
110     // successfully audio packets are received from a client
111     // for the client, enable protocol if the channel is enabled, i.e., the
112     // connection button was hit by the user
113     if ( bIsServer )
114     {
115         return IsConnected();
116     }
117     else
118     {
119         return bIsEnabled;
120     }
121 }
122 
SetEnable(const bool bNEnStat)123 void CChannel::SetEnable ( const bool bNEnStat )
124 {
125     QMutexLocker locker ( &Mutex );
126 
127     // set internal parameter
128     bIsEnabled = bNEnStat;
129 
130     // The support for the packet sequence number must be reset if the client
131     // disconnects from a server since we do not yet know if the next server we
132     // connect to will support the sequence number. We use the SetEnable call in
133     // the client for this task since at every start/stop it will call this
134     // function. NOTE that it is important to reset this parameter on SetEnable(false)
135     // since the SetEnable(true) is set AFTER the Init() in the client -> we
136     // simply set it regardless of the state which does not hurt.
137     bUseSequenceNumber = false;
138 
139     // if channel is not enabled, reset time out count and protocol
140     if ( !bNEnStat )
141     {
142         iConTimeOut = 0;
143         Protocol.Reset();
144     }
145 }
146 
OnVersionAndOSReceived(COSUtil::EOpSystemType eOSType,QString strVersion)147 void CChannel::OnVersionAndOSReceived ( COSUtil::EOpSystemType eOSType, QString strVersion )
148 {
149     // check if audio packet counter is supported by the server (minimum version is 3.6.0)
150 #if QT_VERSION >= QT_VERSION_CHECK( 5, 6, 0 )
151     if ( QVersionNumber::compare ( QVersionNumber::fromString ( strVersion ), QVersionNumber ( 3, 6, 0 ) ) >= 0 )
152     {
153         // activate sequence counter and update the audio stream properties (which
154         // does all the initialization and tells the server about the change)
155         bUseSequenceNumber = true;
156 
157         SetAudioStreamProperties ( eAudioCompressionType, iCeltNumCodedBytes, iNetwFrameSizeFact, iNumAudioChannels );
158     }
159 #endif
160 
161     emit VersionAndOSReceived ( eOSType, strVersion );
162 }
163 
SetAudioStreamProperties(const EAudComprType eNewAudComprType,const int iNewCeltNumCodedBytes,const int iNewNetwFrameSizeFact,const int iNewNumAudioChannels)164 void CChannel::SetAudioStreamProperties ( const EAudComprType eNewAudComprType,
165                                           const int           iNewCeltNumCodedBytes,
166                                           const int           iNewNetwFrameSizeFact,
167                                           const int           iNewNumAudioChannels )
168 {
169     /*
170         this function is intended for the client (not the server)
171     */
172     CNetworkTransportProps NetworkTransportProps;
173 
174     Mutex.lock();
175     {
176         // store new values
177         eAudioCompressionType = eNewAudComprType;
178         iNumAudioChannels     = iNewNumAudioChannels;
179         iCeltNumCodedBytes    = iNewCeltNumCodedBytes;
180         iNetwFrameSizeFact    = iNewNetwFrameSizeFact;
181 
182         // add the size of the optional packet counter
183         if ( bUseSequenceNumber )
184         {
185             iNetwFrameSize = iCeltNumCodedBytes + 1; // per definition 1 byte counter
186         }
187         else
188         {
189             iNetwFrameSize = iCeltNumCodedBytes;
190         }
191 
192         // update audio frame size
193         if ( eAudioCompressionType == CT_OPUS )
194         {
195             iAudioFrameSizeSamples = DOUBLE_SYSTEM_FRAME_SIZE_SAMPLES;
196         }
197         else
198         {
199             iAudioFrameSizeSamples = SYSTEM_FRAME_SIZE_SAMPLES;
200         }
201 
202         MutexSocketBuf.lock();
203         {
204             // init socket buffer
205             SockBuf.SetUseDoubleSystemFrameSize ( eAudioCompressionType == CT_OPUS ); // NOTE must be set BEFORE the init()
206             SockBuf.Init ( iCeltNumCodedBytes, iCurSockBufNumFrames, bUseSequenceNumber );
207         }
208         MutexSocketBuf.unlock();
209 
210         MutexConvBuf.lock();
211         {
212             // init conversion buffer
213             ConvBuf.Init ( iNetwFrameSize * iNetwFrameSizeFact, bUseSequenceNumber );
214         }
215         MutexConvBuf.unlock();
216 
217         // fill network transport properties struct
218         NetworkTransportProps = GetNetworkTransportPropsFromCurrentSettings();
219     }
220     Mutex.unlock();
221 
222     // tell the server about the new network settings
223     Protocol.CreateNetwTranspPropsMes ( NetworkTransportProps );
224 }
225 
SetSockBufNumFrames(const int iNewNumFrames,const bool bPreserve)226 bool CChannel::SetSockBufNumFrames ( const int iNewNumFrames, const bool bPreserve )
227 {
228     bool ReturnValue           = true;  // init with error
229     bool bCurDoAutoSockBufSize = false; // we have to init but init values does not matter
230 
231     // first check for valid input parameter range
232     if ( ( iNewNumFrames >= MIN_NET_BUF_SIZE_NUM_BL ) && ( iNewNumFrames <= MAX_NET_BUF_SIZE_NUM_BL ) )
233     {
234         // only apply parameter if new parameter is different from current one
235         if ( iCurSockBufNumFrames != iNewNumFrames )
236         {
237             MutexSocketBuf.lock();
238             {
239                 // store new value
240                 iCurSockBufNumFrames = iNewNumFrames;
241 
242                 // the network block size is a multiple of the minimum network
243                 // block size
244                 SockBuf.Init ( iCeltNumCodedBytes, iNewNumFrames, bUseSequenceNumber, bPreserve );
245 
246                 // store current auto socket buffer size setting in the mutex
247                 // region since if we use the current parameter below in the
248                 // if condition, it may have been changed in between the time
249                 // when we have left the mutex region and entered the if
250                 // condition
251                 bCurDoAutoSockBufSize = bDoAutoSockBufSize;
252 
253                 ReturnValue = false; // -> no error
254             }
255             MutexSocketBuf.unlock();
256         }
257     }
258 
259     // only in case there is no error, we are the server and auto jitter buffer
260     // setting is enabled, we have to report the current setting to the client
261     if ( !ReturnValue && bIsServer && bCurDoAutoSockBufSize )
262     {
263         // we cannot call the "CreateJitBufMes" function directly since
264         // this would give us problems with different threads (e.g. the
265         // timer thread) and the protocol mechanism (problem with
266         // qRegisterMetaType(), etc.)
267         emit ServerAutoSockBufSizeChange ( iNewNumFrames );
268     }
269 
270     return ReturnValue; // set error flag
271 }
272 
SetGain(const int iChanID,const float fNewGain)273 void CChannel::SetGain ( const int iChanID, const float fNewGain )
274 {
275     QMutexLocker locker ( &Mutex );
276 
277     // set value (make sure channel ID is in range)
278     if ( ( iChanID >= 0 ) && ( iChanID < MAX_NUM_CHANNELS ) )
279     {
280         // signal mute change
281         if ( ( vecfGains[iChanID] == 0 ) && ( fNewGain > 0 ) )
282         {
283             emit MuteStateHasChanged ( iChanID, false );
284         }
285         if ( ( vecfGains[iChanID] > 0 ) && ( fNewGain == 0 ) )
286         {
287             emit MuteStateHasChanged ( iChanID, true );
288         }
289 
290         vecfGains[iChanID] = fNewGain;
291     }
292 }
293 
GetGain(const int iChanID)294 float CChannel::GetGain ( const int iChanID )
295 {
296     QMutexLocker locker ( &Mutex );
297 
298     // get value (make sure channel ID is in range)
299     if ( ( iChanID >= 0 ) && ( iChanID < MAX_NUM_CHANNELS ) )
300     {
301         return vecfGains[iChanID];
302     }
303     else
304     {
305         return 0;
306     }
307 }
308 
SetPan(const int iChanID,const float fNewPan)309 void CChannel::SetPan ( const int iChanID, const float fNewPan )
310 {
311     QMutexLocker locker ( &Mutex );
312 
313     // set value (make sure channel ID is in range)
314     if ( ( iChanID >= 0 ) && ( iChanID < MAX_NUM_CHANNELS ) )
315     {
316         vecfPannings[iChanID] = fNewPan;
317     }
318 }
319 
GetPan(const int iChanID)320 float CChannel::GetPan ( const int iChanID )
321 {
322     QMutexLocker locker ( &Mutex );
323 
324     // get value (make sure channel ID is in range)
325     if ( ( iChanID >= 0 ) && ( iChanID < MAX_NUM_CHANNELS ) )
326     {
327         return vecfPannings[iChanID];
328     }
329     else
330     {
331         return 0;
332     }
333 }
334 
SetChanInfo(const CChannelCoreInfo & NChanInf)335 void CChannel::SetChanInfo ( const CChannelCoreInfo& NChanInf )
336 {
337     bIsIdentified = true; // Indicate we have received channel info
338 
339     // apply value (if different from previous one)
340     if ( ChannelInfo != NChanInf )
341     {
342         ChannelInfo = NChanInf;
343 
344         // fire message that the channel info has changed
345         emit ChanInfoHasChanged();
346     }
347 }
348 
GetName()349 QString CChannel::GetName()
350 {
351     // make sure the string is not written at the same time when it is
352     // read here -> use mutex to secure access
353     QMutexLocker locker ( &Mutex );
354 
355     return ChannelInfo.strName;
356 }
357 
OnSendProtMessage(CVector<uint8_t> vecMessage)358 void CChannel::OnSendProtMessage ( CVector<uint8_t> vecMessage )
359 {
360     // only send messages if protocol is enabled, otherwise delete complete
361     // queue
362     if ( ProtocolIsEnabled() )
363     {
364         // emit message to actually send the data
365         emit MessReadyForSending ( vecMessage );
366     }
367     else
368     {
369         // delete send message queue
370         Protocol.Reset();
371     }
372 }
373 
OnJittBufSizeChange(int iNewJitBufSize)374 void CChannel::OnJittBufSizeChange ( int iNewJitBufSize )
375 {
376     // for server apply setting, for client emit message
377     if ( bIsServer )
378     {
379         // first check for special case: auto setting
380         if ( iNewJitBufSize == AUTO_NET_BUF_SIZE_FOR_PROTOCOL )
381         {
382             SetDoAutoSockBufSize ( true );
383         }
384         else
385         {
386             // manual setting is received, turn OFF auto setting and apply new value
387             SetDoAutoSockBufSize ( false );
388             SetSockBufNumFrames ( iNewJitBufSize, true );
389         }
390     }
391     else
392     {
393         emit JittBufSizeChanged ( iNewJitBufSize );
394     }
395 }
396 
OnChangeChanGain(int iChanID,float fNewGain)397 void CChannel::OnChangeChanGain ( int iChanID, float fNewGain ) { SetGain ( iChanID, fNewGain ); }
398 
OnChangeChanPan(int iChanID,float fNewPan)399 void CChannel::OnChangeChanPan ( int iChanID, float fNewPan ) { SetPan ( iChanID, fNewPan ); }
400 
OnChangeChanInfo(CChannelCoreInfo ChanInfo)401 void CChannel::OnChangeChanInfo ( CChannelCoreInfo ChanInfo ) { SetChanInfo ( ChanInfo ); }
402 
OnNetTranspPropsReceived(CNetworkTransportProps NetworkTransportProps)403 void CChannel::OnNetTranspPropsReceived ( CNetworkTransportProps NetworkTransportProps )
404 {
405     // only the server shall act on network transport properties message
406     if ( bIsServer )
407     {
408         // OPUS and OPUS64 codecs are the only supported codecs right now
409         if ( ( NetworkTransportProps.eAudioCodingType != CT_OPUS ) && ( NetworkTransportProps.eAudioCodingType != CT_OPUS64 ) )
410         {
411             Protocol.CreateOpusSupportedMes();
412             return;
413         }
414 
415         Mutex.lock();
416         {
417             // store received parameters
418             eAudioCompressionType = NetworkTransportProps.eAudioCodingType;
419             iNumAudioChannels     = static_cast<int> ( NetworkTransportProps.iNumAudioChannels );
420             iNetwFrameSizeFact    = NetworkTransportProps.iBlockSizeFact;
421             iNetwFrameSize        = static_cast<int> ( NetworkTransportProps.iBaseNetworkPacketSize );
422             bUseSequenceNumber    = ( NetworkTransportProps.eFlags == NF_WITH_COUNTER );
423 
424             if ( bUseSequenceNumber )
425             {
426                 iCeltNumCodedBytes = iNetwFrameSize - 1; // per definition 1 byte counter
427             }
428             else
429             {
430                 iCeltNumCodedBytes = iNetwFrameSize;
431             }
432 
433             // update maximum number of frames for fade in counter (only needed for server)
434             // and audio frame size
435             if ( eAudioCompressionType == CT_OPUS )
436             {
437                 iFadeInCntMax          = FADE_IN_NUM_FRAMES_DBLE_FRAMESIZE / iNetwFrameSizeFact;
438                 iAudioFrameSizeSamples = DOUBLE_SYSTEM_FRAME_SIZE_SAMPLES;
439             }
440             else
441             {
442                 iFadeInCntMax          = FADE_IN_NUM_FRAMES / iNetwFrameSizeFact;
443                 iAudioFrameSizeSamples = SYSTEM_FRAME_SIZE_SAMPLES;
444             }
445 
446             // the fade-in counter maximum value may have changed, make sure the fade-in counter
447             // is not larger than the allowed maximum value
448             iFadeInCnt = std::min ( iFadeInCnt, iFadeInCntMax );
449 
450             MutexSocketBuf.lock();
451             {
452                 // update socket buffer (the network block size is a multiple of the
453                 // minimum network frame size)
454                 SockBuf.SetUseDoubleSystemFrameSize ( eAudioCompressionType == CT_OPUS ); // NOTE must be set BEFORE the init()
455                 SockBuf.Init ( iCeltNumCodedBytes, iCurSockBufNumFrames, bUseSequenceNumber );
456             }
457             MutexSocketBuf.unlock();
458 
459             MutexConvBuf.lock();
460             {
461                 // init conversion buffer
462                 ConvBuf.Init ( iNetwFrameSize * iNetwFrameSizeFact, bUseSequenceNumber );
463             }
464             MutexConvBuf.unlock();
465         }
466         Mutex.unlock();
467     }
468 }
469 
OnReqNetTranspProps()470 void CChannel::OnReqNetTranspProps()
471 {
472     // fill network transport properties struct from current settings and send it
473     Protocol.CreateNetwTranspPropsMes ( GetNetworkTransportPropsFromCurrentSettings() );
474 }
475 
OnReqSplitMessSupport()476 void CChannel::OnReqSplitMessSupport()
477 {
478     // activate split messages in our protocol (client) and return answer message to the server
479     Protocol.SetSplitMessageSupported ( true );
480     Protocol.CreateSplitMessSupportedMes();
481 }
482 
GetNetworkTransportPropsFromCurrentSettings()483 CNetworkTransportProps CChannel::GetNetworkTransportPropsFromCurrentSettings()
484 {
485     // set network flags
486     ENetwFlags eFlags = NF_NONE;
487 
488     if ( bUseSequenceNumber )
489     {
490         eFlags = NF_WITH_COUNTER;
491     }
492 
493     // use current stored settings of the channel to fill the network transport
494     // properties structure
495     return CNetworkTransportProps ( static_cast<uint32_t> ( iNetwFrameSize ),
496                                     static_cast<uint16_t> ( iNetwFrameSizeFact ),
497                                     static_cast<uint32_t> ( iNumAudioChannels ),
498                                     SYSTEM_SAMPLE_RATE_HZ,
499                                     eAudioCompressionType,
500                                     eFlags,
501                                     0 );
502 }
503 
Disconnect()504 void CChannel::Disconnect()
505 {
506     // we only have to disconnect the channel if it is actually connected
507     if ( IsConnected() )
508     {
509         // set time out counter to a small value > 0 so that the next time a
510         // received audio block is queried, the disconnection is performed
511         // (assuming that no audio packet is received in the meantime)
512         iConTimeOut = 1; // a small number > 0
513     }
514 }
515 
PutProtcolData(const int iRecCounter,const int iRecID,const CVector<uint8_t> & vecbyMesBodyData,const CHostAddress & RecHostAddr)516 void CChannel::PutProtcolData ( const int iRecCounter, const int iRecID, const CVector<uint8_t>& vecbyMesBodyData, const CHostAddress& RecHostAddr )
517 {
518     // Only process protocol message if:
519     // - for client only: the packet comes from the server we want to talk to
520     // - the channel is enabled
521     // - the protocol mechanism is enabled
522     if ( ( bIsServer || ( GetAddress() == RecHostAddr ) ) && IsEnabled() && ProtocolIsEnabled() )
523     {
524         // parse the message assuming this is a regular protocol message
525         Protocol.ParseMessageBody ( vecbyMesBodyData, iRecCounter, iRecID );
526     }
527 }
528 
PutAudioData(const CVector<uint8_t> & vecbyData,const int iNumBytes,CHostAddress RecHostAddr)529 EPutDataStat CChannel::PutAudioData ( const CVector<uint8_t>& vecbyData, const int iNumBytes, CHostAddress RecHostAddr )
530 {
531     // init return state
532     EPutDataStat eRet = PS_GEN_ERROR;
533 
534     // Only process audio data if:
535     // - for client only: the packet comes from the server we want to talk to
536     // - the channel is enabled
537     if ( ( bIsServer || ( GetAddress() == RecHostAddr ) ) && IsEnabled() )
538     {
539         MutexSocketBuf.lock();
540         {
541             // only process audio if packet has correct size
542             if ( iNumBytes == ( iNetwFrameSize * iNetwFrameSizeFact ) )
543             {
544                 // store new packet in jitter buffer
545                 if ( SockBuf.Put ( vecbyData, iNumBytes ) )
546                 {
547                     eRet = PS_AUDIO_OK;
548                 }
549                 else
550                 {
551                     eRet = PS_AUDIO_ERR;
552                 }
553 
554                 // manage audio fade-in counter, after channel is identified
555                 if ( iFadeInCnt < iFadeInCntMax && bIsIdentified )
556                 {
557                     iFadeInCnt++;
558                 }
559             }
560             else
561             {
562                 // the protocol parsing failed and this was no audio block,
563                 // we treat this as protocol error (unknown packet)
564                 eRet = PS_PROT_ERR;
565             }
566 
567             // All network packets except of valid protocol messages
568             // regardless if they are valid or invalid audio packets lead to
569             // a state change to a connected channel.
570             // This is because protocol messages can only be sent on a
571             // connected channel and the client has to inform the server
572             // about the audio packet properties via the protocol.
573 
574             // check if channel was not connected, this is a new connection
575             if ( !IsConnected() )
576             {
577                 // overwrite status
578                 eRet = PS_NEW_CONNECTION;
579 
580                 // init audio fade-in counter
581                 iFadeInCnt = 0;
582 
583                 // init level meter
584                 SignalLevelMeter.Reset();
585             }
586 
587             // reset time-out counter (note that this must be done after the
588             // "IsConnected()" query above)
589             ResetTimeOutCounter();
590         }
591         MutexSocketBuf.unlock();
592     }
593     else
594     {
595         eRet = PS_AUDIO_INVALID;
596     }
597 
598     return eRet;
599 }
600 
GetData(CVector<uint8_t> & vecbyData,const int iNumBytes)601 EGetDataStat CChannel::GetData ( CVector<uint8_t>& vecbyData, const int iNumBytes )
602 {
603     EGetDataStat eGetStatus;
604 
605     MutexSocketBuf.lock();
606     {
607         // the socket access must be inside a mutex
608         const bool bSockBufState = SockBuf.Get ( vecbyData, iNumBytes );
609 
610         // decrease time-out counter
611         if ( iConTimeOut > 0 )
612         {
613             // subtract the number of samples of the current block since the
614             // time out counter is based on samples not on blocks (definition:
615             // always one atomic block is get by using the GetData() function
616             // where the atomic block size is "iAudioFrameSizeSamples")
617             iConTimeOut -= iAudioFrameSizeSamples;
618 
619             if ( iConTimeOut <= 0 )
620             {
621                 // channel is just disconnected
622                 eGetStatus  = GS_CHAN_NOW_DISCONNECTED;
623                 iConTimeOut = 0; // make sure we do not have negative values
624 
625                 // reset network transport properties
626                 ResetNetworkTransportProperties();
627             }
628             else
629             {
630                 if ( bSockBufState )
631                 {
632                     // everything is ok
633                     eGetStatus = GS_BUFFER_OK;
634                 }
635                 else
636                 {
637                     // channel is not yet disconnected but no data in buffer
638                     eGetStatus = GS_BUFFER_UNDERRUN;
639                 }
640             }
641         }
642         else
643         {
644             // channel is disconnected
645             eGetStatus = GS_CHAN_NOT_CONNECTED;
646         }
647     }
648     MutexSocketBuf.unlock();
649 
650     // in case we are just disconnected, we have to fire a message
651     if ( eGetStatus == GS_CHAN_NOW_DISCONNECTED )
652     {
653         // reset the protocol
654         Protocol.Reset();
655 
656         // emit message
657         emit Disconnected();
658     }
659 
660     return eGetStatus;
661 }
662 
PrepAndSendPacket(CHighPrioSocket * pSocket,const CVector<uint8_t> & vecbyNPacket,const int iNPacketLen)663 void CChannel::PrepAndSendPacket ( CHighPrioSocket* pSocket, const CVector<uint8_t>& vecbyNPacket, const int iNPacketLen )
664 {
665     // From v3.8.0 onwards, a server will not send audio to a client until that client has sent channel info.
666     // This addresses #1243 but means that clients earlier than v3.3.0 (24 Feb 2013) will no longer be compatible.
667     if ( bIsServer && !bIsIdentified )
668     {
669         return;
670     }
671 
672     QMutexLocker locker ( &MutexConvBuf );
673 
674     // use conversion buffer to convert sound card block size in network
675     // block size and take care of optional sequence number (note that
676     // the sequence number wraps automatically)
677     if ( ConvBuf.Put ( vecbyNPacket, iNPacketLen, iSendSequenceNumber++ ) )
678     {
679         pSocket->SendPacket ( ConvBuf.GetAll(), GetAddress() );
680     }
681 }
682 
UpdateAndGetLevelForMeterdB(const CVector<short> & vecsAudio,const int iInSize,const bool bIsStereoIn)683 double CChannel::UpdateAndGetLevelForMeterdB ( const CVector<short>& vecsAudio, const int iInSize, const bool bIsStereoIn )
684 {
685     // update the signal level meter and immediately return the current value
686     SignalLevelMeter.Update ( vecsAudio, iInSize, bIsStereoIn );
687 
688     return SignalLevelMeter.GetLevelForMeterdBLeftOrMono();
689 }
690 
GetUploadRateKbps()691 int CChannel::GetUploadRateKbps()
692 {
693     const int iAudioSizeOut = iNetwFrameSizeFact * iAudioFrameSizeSamples;
694 
695     // we assume that the UDP packet which is transported via IP has an
696     // additional header size of ("Network Music Performance (NMP) in narrow
697     // band networks; Carot, Kraemer, Schuller; 2006")
698     // 8 (UDP) + 20 (IP without optional fields) = 28 bytes
699     // 2 (PPP) + 6 (PPPoE) + 18 (MAC)            = 26 bytes
700     // 5 (RFC1483B) + 8 (AAL) + 10 (ATM)         = 23 bytes
701     return ( iNetwFrameSize * iNetwFrameSizeFact + 28 + 26 + 23 /* header */ ) * 8 /* bits per byte */ * SYSTEM_SAMPLE_RATE_HZ / iAudioSizeOut / 1000;
702 }
703 
UpdateSocketBufferSize()704 void CChannel::UpdateSocketBufferSize()
705 {
706     // just update the socket buffer size if auto setting is enabled, otherwise
707     // do nothing
708     if ( bDoAutoSockBufSize )
709     {
710         // use auto setting result from channel, make sure we preserve the
711         // buffer memory since we just adjust the size here
712         SetSockBufNumFrames ( SockBuf.GetAutoSetting(), true );
713     }
714 }
715