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