@babblevoice/projectrtp 2.5.35 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -128,13 +128,12 @@ projectrtpchannel::projectrtpchannel( unsigned short port ):
128
128
  outcodec(),
129
129
  incodec(),
130
130
  player( nullptr ),
131
- newplaydef( nullptr ),
132
- newplaylock( false ),
131
+ playerstash( nullptr ),
132
+ playerlock( false ),
133
133
  doecho( false ),
134
134
  tick( workercontext ),
135
135
  nexttick( std::chrono::high_resolution_clock::now() ),
136
- newrecorders(),
137
- newrecorderslock( false ),
136
+ recorderslock( false ),
138
137
  recorders(),
139
138
  rtpdtls( nullptr ),
140
139
  rtpdtlslock( false ),
@@ -144,6 +143,7 @@ projectrtpchannel::projectrtpchannel( unsigned short port ):
144
143
  remoteport( 0 ),
145
144
  queueddigits(),
146
145
  queuddigitslock( false ),
146
+ dtmfsendcount( 0 ),
147
147
  lastdtmfsn( 0 ),
148
148
  tickstarttime() {
149
149
 
@@ -418,16 +418,17 @@ void projectrtpchannel::doclose( void ) {
418
418
  if( !this->active ) return;
419
419
  this->active = false;
420
420
 
421
- this->tick.cancel();
421
+ auto self = shared_from_this();
422
422
 
423
- if( nullptr != this->player ) {
424
- postdatabacktojsfromthread( shared_from_this(), "play", "end", "channelclosed" );
425
- }
423
+ this->tick.cancel();
426
424
 
427
425
  {
428
- SpinLockGuard guard( this->newplaylock );
426
+ SpinLockGuard guard( this->playerlock );
427
+ if( nullptr != this->player ) {
428
+ postdatabacktojsfromthread( self, "play", "end", "channelclosed" );
429
+ }
430
+
429
431
  this->player = nullptr;
430
- this->newplaydef = nullptr;
431
432
  }
432
433
 
433
434
  /* close our session if we have one */
@@ -437,11 +438,15 @@ void projectrtpchannel::doclose( void ) {
437
438
  }
438
439
 
439
440
  /* close up any remaining recorders */
440
- for( auto& rec: this->recorders ) {
441
- postdatabacktojsfromthread( shared_from_this(), "record", rec->file, "finished.channelclosed" );
441
+ {
442
+ SpinLockGuard guard( this->recorderslock );
443
+ for( auto& rec: this->recorders ) {
444
+ postdatabacktojsfromthread( self, "record", rec->file, "finished.channelclosed" );
445
+ }
446
+
447
+ this->recorders.clear();
442
448
  }
443
449
 
444
- this->recorders.clear();
445
450
  this->resolver.cancel();
446
451
 
447
452
  this->rtpsocket.close();
@@ -449,7 +454,7 @@ void projectrtpchannel::doclose( void ) {
449
454
 
450
455
  this->returnavailableport();
451
456
 
452
- postdatabacktojsfromthread( shared_from_this(), "close", this->closereason );
457
+ postdatabacktojsfromthread( self, "close", this->closereason );
453
458
  }
454
459
 
455
460
  bool projectrtpchannel::checkidlerecv( void ) {
@@ -470,6 +475,13 @@ bool projectrtpchannel::checkidlerecv( void ) {
470
475
  this->doclose();
471
476
  return true;
472
477
  }
478
+ } else if( this->active ) {
479
+ /* active but not receiving ie on hold or similar - but there are limits! */
480
+ if( this->hardtickswithnortpcount > ( 50 * 60 * 60 * 2 ) ) { /* 2hr hard timeout */
481
+ this->closereason = "idle";
482
+ this->doclose();
483
+ return true;
484
+ }
473
485
  }
474
486
  return false;
475
487
  }
@@ -486,6 +498,8 @@ void projectrtpchannel::handletick( const boost::system::error_code& error ) {
486
498
  if( error == boost::asio::error::operation_aborted ) return;
487
499
  if( !this->active ) return;
488
500
 
501
+ auto self = shared_from_this();
502
+
489
503
  if( this->_requestclose ) {
490
504
  this->doclose();
491
505
  return;
@@ -510,11 +524,15 @@ void projectrtpchannel::handletick( const boost::system::error_code& error ) {
510
524
  return;
511
525
  }
512
526
 
513
- this->checkfornewrecorders();
514
-
515
527
  this->incodec << codecx::next;
516
528
  this->outcodec << codecx::next;
517
529
 
530
+ soundsoup::pointer ourplayer = nullptr;
531
+ {
532
+ SpinLockGuard guard( this->playerlock );
533
+ ourplayer = this->player;
534
+ }
535
+
518
536
  rtppacket *src;
519
537
  do {
520
538
  {
@@ -543,36 +561,10 @@ void projectrtpchannel::handletick( const boost::system::error_code& error ) {
543
561
  this->incodec << *src;
544
562
  }
545
563
 
546
- /* check for new players */
547
- {
548
- bool playerreplaced = false;
549
- bool playernew = false;
550
- {
551
- SpinLockGuard guard( this->newplaylock );
552
- if( nullptr != this->newplaydef ) {
553
- this->doecho = false;
554
-
555
- if( nullptr != this->player ) {
556
- playerreplaced = true;
557
- }
558
-
559
- this->player = this->newplaydef;
560
- this->newplaydef = nullptr;
561
- playernew = true;
562
- }
563
- }
564
-
565
- if( playerreplaced ) {
566
- postdatabacktojsfromthread( shared_from_this(), "play", "end", "replaced" );
567
- }
568
- if( playernew ) {
569
- postdatabacktojsfromthread( shared_from_this(), "play", "start", "new" );
570
- }
571
- }
572
-
573
564
  if( this->doecho ) {
574
- if( this->player ) {
575
- postdatabacktojsfromthread( shared_from_this(), "play", "end", "doecho" );
565
+ if( ourplayer ) {
566
+ postdatabacktojsfromthread( self, "play", "end", "doecho" );
567
+ SpinLockGuard guard( this->playerlock );
576
568
  this->player = nullptr;
577
569
  }
578
570
 
@@ -583,20 +575,21 @@ void projectrtpchannel::handletick( const boost::system::error_code& error ) {
583
575
  dst << this->outcodec;
584
576
  this->writepacket( dst );
585
577
  }
586
- } else if( this->player ) {
578
+ } else if( ourplayer ) {
587
579
  rtppacket *out = this->gettempoutbuf();
588
580
  rawsound r;
589
- if( this->player->read( r ) ) {
581
+ if( ourplayer->read( r ) ) {
590
582
  if( r.size() > 0 ) {
591
583
  this->outcodec << r;
592
584
  out << this->outcodec;
593
585
  this->writepacket( out );
594
586
  }
595
587
  } else {
588
+ postdatabacktojsfromthread( self, "play", "end", "completed" );
589
+ SpinLockGuard guard( this->playerlock );
596
590
  this->player = nullptr;
597
- postdatabacktojsfromthread( shared_from_this(), "play", "end", "completed" );
598
591
  }
599
- }
592
+ }
600
593
 
601
594
  this->writerecordings();
602
595
 
@@ -628,50 +621,47 @@ void projectrtpchannel::setnexttick( void ) {
628
621
  }
629
622
 
630
623
  void projectrtpchannel::requestplay( soundsoup::pointer newdef ) {
631
- SpinLockGuard guard( this->newplaylock );
632
- this->newplaydef = newdef;
624
+ SpinLockGuard guard( this->playerlock );
625
+
626
+ auto self = shared_from_this();
627
+
628
+ this->doecho = false;
629
+
630
+ if( nullptr != this->player ) {
631
+ postdatabacktojsfromthread( self, "play", "end", "replaced" );
632
+ }
633
+
634
+ postdatabacktojsfromthread( self, "play", "start", "new" );
635
+ this->player = newdef;
633
636
  }
634
637
 
635
638
  /*
636
639
  Post a request to record (or modify a param of a record). This function is typically
637
640
  called from a control thread (i.e. node).
638
641
  */
639
- void projectrtpchannel::requestrecord( channelrecorder::pointer rec ) {
640
- SpinLockGuard guard( this->newrecorderslock );
641
- this->newrecorders.push_back( rec );
642
- }
643
-
644
- /*
645
- Check for new channels to add to the mix in our own thread. This will be a different thread
646
- to requestrecord.
647
- */
648
- void projectrtpchannel::checkfornewrecorders( void ) {
649
- channelrecorder::pointer rec;
650
- SpinLockGuard guard( this->newrecorderslock );
651
-
652
- for ( auto const& newrec : this->newrecorders ) {
653
- for( auto& currentrec: this->recorders ) {
654
- if( currentrec->file == newrec->file ) {
655
- currentrec->pause = newrec->pause;
656
- currentrec->requestfinish = newrec->requestfinish;
657
- goto endofwhileloop;
658
- }
642
+ void projectrtpchannel::requestrecord( channelrecorder::pointer newrec ) {
643
+ SpinLockGuard guard( this->recorderslock );
644
+
645
+ for( auto& currentrec: this->recorders ) {
646
+ if( currentrec->file == newrec->file ) {
647
+ currentrec->pause.store( newrec->pause );
648
+ currentrec->requestfinish.store( newrec->requestfinish );
649
+ return;
659
650
  }
651
+ }
660
652
 
661
- newrec->sfile = soundfilewriter::create(
662
- newrec->file,
663
- newrec->numchannels,
664
- soundfile::getsampleratefrompt( this->codec ) );
665
-
666
- this->recorders.push_back( newrec );
653
+ newrec->sfile = soundfilewriter::create(
654
+ newrec->file,
655
+ newrec->numchannels,
656
+ soundfile::getsampleratefrompt( this->codec ) );
667
657
 
668
- endofwhileloop:;
669
- }
670
658
 
671
- this->newrecorders.clear();
659
+ this->recorders.push_back( newrec );
672
660
  }
673
661
 
674
- void projectrtpchannel::removeoldrecorders( void ) {
662
+ void projectrtpchannel::removeoldrecorders( pointer self ) {
663
+
664
+ SpinLockGuard guard( this->recorderslock );
675
665
 
676
666
  for ( auto const& rec : this->recorders ) {
677
667
  if( rec->isactive() ) {
@@ -686,7 +676,7 @@ void projectrtpchannel::removeoldrecorders( void ) {
686
676
  if( rec->requestfinish ) {
687
677
  rec->completed = true;
688
678
  rec->maxsincestartpower = 0;
689
- postdatabacktojsfromthread( shared_from_this(), "record", rec->file, "finished.requested" );
679
+ postdatabacktojsfromthread( self, "record", rec->file, "finished.requested" );
690
680
  continue;
691
681
  }
692
682
 
@@ -699,14 +689,14 @@ void projectrtpchannel::removeoldrecorders( void ) {
699
689
  rec->lastpowercalc < rec->finishbelowpower ) {
700
690
  rec->completed = true;
701
691
  rec->maxsincestartpower = 0;
702
- postdatabacktojsfromthread( shared_from_this(), "record", rec->file, "finished.belowpower" );
692
+ postdatabacktojsfromthread( self, "record", rec->file, "finished.belowpower" );
703
693
  continue;
704
694
  }
705
695
 
706
696
  if( 0 != rec->maxduration && diff.total_milliseconds() > rec->maxduration ) {
707
697
  rec->completed = true;
708
698
  rec->maxsincestartpower = 0;
709
- postdatabacktojsfromthread( shared_from_this(), "record", rec->file, "finished.timeout" );
699
+ postdatabacktojsfromthread( self, "record", rec->file, "finished.timeout" );
710
700
  continue;
711
701
  }
712
702
  }
@@ -725,12 +715,15 @@ bool projectrtpchannel::recordercompleted( const channelrecorder::pointer& rec )
725
715
  */
726
716
  static char dtmfchars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '*', '#', 'A', 'B', 'C', 'D', 'F' };
727
717
  void projectrtpchannel::sendtelevent( void ) {
718
+ auto self = shared_from_this();
719
+ SpinLockGuard guard( this->playerlock );
720
+
728
721
  if( this->player && this->player->doesinterupt() ) {
729
- postdatabacktojsfromthread( shared_from_this(), "play", "end", "telephone-event" );
722
+ postdatabacktojsfromthread( self, "play", "end", "telephone-event" );
730
723
  this->player = nullptr;
731
724
  }
732
725
 
733
- postdatabacktojsfromthread( shared_from_this(), "telephone-event", std::string( 1, dtmfchars[ this->lasttelephoneevent ] ) );
726
+ postdatabacktojsfromthread( self, "telephone-event", std::string( 1, dtmfchars[ this->lasttelephoneevent ] ) );
734
727
  }
735
728
  /*
736
729
  ## checkfordtmf
@@ -785,11 +778,22 @@ If our codecs (in and out) have data then write to recorded files.
785
778
  */
786
779
  void projectrtpchannel::writerecordings( void ) {
787
780
 
788
- if( 0 == this->recorders.size() ) return;
781
+ if( !this->active ) return;
782
+
783
+ auto self = shared_from_this();
784
+
785
+ chanrecptrlist worklist;
786
+ {
787
+ SpinLockGuard guard( this->recorderslock );
788
+ worklist = this->recorders;
789
+ }
790
+
791
+ if( 0 == worklist.size() ) return;
792
+
789
793
  uint16_t power = 0;
790
794
 
791
795
  /* Decide if we need to calc power as it is expensive */
792
- for( auto& rec: this->recorders ) {
796
+ for( auto& rec: worklist ) {
793
797
  if( ( !rec->isactive() && 0 != rec->startabovepower ) || 0 != rec->finishbelowpower ) {
794
798
  power = this->incodec.power();
795
799
  break;
@@ -797,7 +801,7 @@ void projectrtpchannel::writerecordings( void ) {
797
801
  }
798
802
 
799
803
  /* Check if we need to trigger the start of any recordings and write */
800
- for( auto& rec: this->recorders ) {
804
+ for( auto& rec: worklist ) {
801
805
 
802
806
  if( rec->completed ) continue;
803
807
 
@@ -812,11 +816,11 @@ void projectrtpchannel::writerecordings( void ) {
812
816
  if( !rec->isactive() ) {
813
817
  if( 0 == rec->startabovepower ) {
814
818
  rec->active();
815
- postdatabacktojsfromthread( shared_from_this(), "record", rec->file, "recording" );
819
+ postdatabacktojsfromthread( self, "record", rec->file, "recording" );
816
820
  } else {
817
821
  if( pav > rec->startabovepower ) {
818
822
  rec->active();
819
- postdatabacktojsfromthread( shared_from_this(), "record", rec->file, "recording.abovepower" );
823
+ postdatabacktojsfromthread( self, "record", rec->file, "recording.abovepower" );
820
824
  }
821
825
  }
822
826
  }
@@ -826,7 +830,9 @@ void projectrtpchannel::writerecordings( void ) {
826
830
  }
827
831
  }
828
832
 
829
- this->removeoldrecorders();
833
+ /* this function is also protected by this->recorderslock - so ensure it is free before calling */
834
+ /* pass in sefl to ensure no gap in destruction/auto ptr destruction */
835
+ this->removeoldrecorders( self );
830
836
  }
831
837
 
832
838
  bool projectrtpchannel::dtlsnegotiate( void ) {
@@ -1148,30 +1154,49 @@ bool projectrtpchannel::mix( projectrtpchannel::pointer other ) {
1148
1154
  return true;
1149
1155
  }
1150
1156
 
1151
- SpinLockGuard guard( this->mixerlock );
1157
+ auto self = shared_from_this();
1158
+
1159
+ {
1160
+ SpinLockGuard guard( this->playerlock );
1161
+ if( nullptr != this->player ) {
1162
+ postdatabacktojsfromthread( self, "play", "end", "channelmixing" );
1163
+ }
1164
+ this->player = nullptr;
1165
+ }
1166
+ {
1167
+ SpinLockGuard guard( other->playerlock );
1168
+ if( nullptr != other->player ) {
1169
+ postdatabacktojsfromthread( other, "play", "end", "channelmixing" );
1170
+ }
1171
+ other->player = nullptr;
1172
+ }
1152
1173
 
1153
- if( nullptr == this->mixer && nullptr != other->mixer ) {
1154
- this->mixer = other->mixer;
1155
- this->mixer->addchannel( shared_from_this() );
1174
+ {
1175
+ SpinLockGuard guard( this->mixerlock );
1156
1176
 
1157
- } else if ( nullptr != this->mixer && nullptr == other->mixer ) {
1158
- other->mixer = this->mixer;
1159
- this->mixer->addchannel( other );
1177
+ if( nullptr == this->mixer && nullptr != other->mixer ) {
1178
+ this->mixer = other->mixer;
1179
+ this->mixer->addchannel( self );
1160
1180
 
1161
- } else if( nullptr == this->mixer && nullptr == other->mixer ) {
1162
- this->mixer = projectchannelmux::create( workercontext );
1163
- other->mixer = this->mixer;
1181
+ } else if ( nullptr != this->mixer && nullptr == other->mixer ) {
1182
+ other->mixer = this->mixer;
1183
+ this->mixer->addchannel( other );
1164
1184
 
1165
- this->mixer->addchannels( shared_from_this(), other );
1185
+ } else if( nullptr == this->mixer && nullptr == other->mixer ) {
1186
+ this->mixer = projectchannelmux::create( workercontext );
1187
+ other->mixer = this->mixer;
1166
1188
 
1167
- this->mixer->go();
1168
- } else {
1169
- /* If we get here this and other are already mixing and should be cleaned up first */
1170
- postdatabacktojsfromthread( shared_from_this(), "mix", "busy" );
1171
- return false;
1189
+ this->mixer->addchannels( self, other );
1190
+
1191
+ this->mixer->go();
1192
+ } else {
1193
+ /* If we get here this and other are already mixing and should be cleaned up first */
1194
+ postdatabacktojsfromthread( self, "mix", "busy" );
1195
+ return false;
1196
+ }
1172
1197
  }
1173
1198
 
1174
- postdatabacktojsfromthread( shared_from_this(), "mix", "start" );
1199
+ postdatabacktojsfromthread( self, "mix", "start" );
1175
1200
  postdatabacktojsfromthread( other, "mix", "start" );
1176
1201
 
1177
1202
  return true;
@@ -1217,6 +1242,12 @@ void projectrtpchannel::dtmf( std::string digits ) {
1217
1242
  this->queueddigits += digits;
1218
1243
  }
1219
1244
 
1245
+ const char volume = 10;
1246
+ const char endofevent = 0x80;
1247
+
1248
+ const int numevents = 3;
1249
+ const int numendevents = 3;
1250
+
1220
1251
  /*
1221
1252
  Now send each digit.
1222
1253
  */
@@ -1231,7 +1262,6 @@ void projectrtpchannel::senddtmf( void ) {
1231
1262
  SpinLockGuard guard( this->queuddigitslock );
1232
1263
  if( this->queueddigits.size() > 0 ) {
1233
1264
  tosend = this->queueddigits[ 0 ];
1234
- this->queueddigits.erase( this->queueddigits.begin() );
1235
1265
  }
1236
1266
  }
1237
1267
 
@@ -1265,77 +1295,42 @@ void projectrtpchannel::senddtmf( void ) {
1265
1295
  return;
1266
1296
  }
1267
1297
 
1268
- const char volume = 10;
1269
- const char endofevent = 0x80;
1270
-
1271
- rtppacket *dst = this->gettempoutbuf();
1272
- dst->setpayloadtype( this->rfc2833pt );
1273
- dst->setpayloadlength( 4 );
1274
- uint8_t *pl = dst->getpayload();
1275
- pl[ 0 ] = tosend;
1276
- pl[ 1 ] = volume; /* end of event & reserved & volume */
1277
- uint16_t *tmp = ( uint16_t * ) &pl[ 2 ]; /* event duration */
1278
- *tmp = htons( 160 );
1279
-
1280
- this->writepacket( dst );
1281
-
1282
- dst = this->gettempoutbuf();
1283
- dst->setpayloadtype( this->rfc2833pt );
1284
- dst->setpayloadlength( 4 );
1285
- pl = dst->getpayload();
1286
- pl[ 0 ] = tosend;
1287
- pl[ 1 ] = volume; /* end of event & reserved & volume */
1288
- tmp = ( uint16_t * ) &pl[ 2 ]; /* event duration */
1289
- *tmp = htons( 320 );
1290
-
1291
- this->writepacket( dst );
1292
-
1293
- dst = this->gettempoutbuf();
1294
- dst->setpayloadtype( this->rfc2833pt );
1295
- dst->setpayloadlength( 4 );
1296
- pl = dst->getpayload();
1297
- pl[ 0 ] = tosend;
1298
- pl[ 1 ] = volume; /* end of event & reserved & volume */
1299
- tmp = ( uint16_t * ) &pl[ 2 ]; /* event duration */
1300
- *tmp = htons( 480 );
1301
-
1302
- this->writepacket( dst );
1303
-
1304
- dst = this->gettempoutbuf();
1305
- dst->setpayloadtype( this->rfc2833pt );
1306
- dst->setmarker();
1307
- dst->setpayloadlength( 4 );
1308
- pl = dst->getpayload();
1309
- pl[ 0 ] = tosend;
1310
- pl[ 1 ] = endofevent | volume; /* end of event & reserved & volume */
1311
- tmp = ( uint16_t * ) &pl[ 2 ]; /* event duration */
1312
- *tmp = htons( 640 );
1313
-
1314
- this->writepacket( dst );
1315
-
1316
- dst = this->gettempoutbuf();
1317
- dst->setpayloadtype( this->rfc2833pt );
1318
- dst->setpayloadlength( 4 );
1319
- pl = dst->getpayload();
1320
- pl[ 0 ] = tosend;
1321
- pl[ 1 ] = endofevent | volume; /* end of event & reserved & volume */
1322
- tmp = ( uint16_t * ) &pl[ 2 ]; /* event duration */
1323
- *tmp = htons( 640 );
1324
-
1325
- this->writepacket( dst );
1326
-
1327
- dst = this->gettempoutbuf();
1328
- dst->setpayloadtype( this->rfc2833pt );
1329
- dst->setpayloadlength( 4 );
1330
- pl = dst->getpayload();
1331
- pl[ 0 ] = tosend;
1332
- pl[ 1 ] = endofevent | volume; /* end of event & reserved & volume */
1333
- tmp = ( uint16_t * ) &pl[ 2 ]; /* event duration */
1334
- *tmp = htons( 640 );
1335
-
1336
- this->writepacket( dst );
1337
-
1338
- this->lastdtmfsn = this->snout;
1298
+ if( this->dtmfsendcount <= numevents ) {
1299
+ rtppacket *dst = this->gettempoutbuf();
1300
+ dst->setpayloadtype( this->rfc2833pt );
1301
+ dst->setpayloadlength( 4 );
1302
+ uint8_t *pl = dst->getpayload();
1303
+ pl[ 0 ] = tosend;
1304
+ pl[ 1 ] = volume; /* end of event & reserved & volume */
1305
+ uint16_t *tmp = ( uint16_t * ) &pl[ 2 ]; /* event duration */
1306
+ *tmp = htons( ( this->dtmfsendcount + 1 ) * 160 );
1307
+
1308
+ this->writepacket( dst );
1309
+
1310
+ } else {
1311
+ /* end packet */
1312
+ rtppacket *dst = this->gettempoutbuf();
1313
+ dst->setpayloadtype( this->rfc2833pt );
1314
+ dst->setmarker();
1315
+ dst->setpayloadlength( 4 );
1316
+ uint8_t *pl = dst->getpayload();
1317
+ pl[ 0 ] = tosend;
1318
+ pl[ 1 ] = endofevent | volume; /* end of event & reserved & volume */
1319
+ uint16_t *tmp = ( uint16_t * ) &pl[ 2 ]; /* event duration */
1320
+ *tmp = htons( ( numevents + 2 ) * 160 );
1321
+
1322
+ this->writepacket( dst );
1323
+ }
1324
+
1325
+ if( this->dtmfsendcount >= ( numevents + numendevents ) ) {
1326
+ SpinLockGuard guard( this->queuddigitslock );
1327
+ this->queueddigits.erase( this->queueddigits.begin() );
1328
+ this->lastdtmfsn = this->snout;
1329
+ this->dtmfsendcount = 0;
1330
+ return;
1331
+ }
1332
+
1333
+ this->dtmfsendcount++;
1339
1334
  }
1340
1335
 
1341
1336
  /*
@@ -196,8 +196,7 @@ private:
196
196
  void incrtsout( void );
197
197
 
198
198
  bool checkidlerecv( void );
199
- void checkfornewrecorders( void );
200
- void removeoldrecorders( void );
199
+ void removeoldrecorders( pointer );
201
200
  void writerecordings( void );
202
201
 
203
202
  bool checkfordtmf( rtppacket *src );
@@ -234,15 +233,14 @@ private:
234
233
  codecx incodec;
235
234
 
236
235
  soundsoup::pointer player;
237
- soundsoup::pointer newplaydef;
238
- std::atomic_bool newplaylock;
236
+ soundsoup::pointer playerstash;
237
+ std::atomic_bool playerlock;
239
238
 
240
239
  std::atomic_bool doecho;
241
240
  boost::asio::steady_timer tick;
242
241
  std::chrono::high_resolution_clock::time_point nexttick;
243
242
 
244
- chanrecptrlist newrecorders;
245
- std::atomic_bool newrecorderslock;
243
+ std::atomic_bool recorderslock;
246
244
  chanrecptrlist recorders;
247
245
 
248
246
  /* DTLS Session */
@@ -258,6 +256,7 @@ private:
258
256
  /* outbound DTMF */
259
257
  std::string queueddigits;
260
258
  std::atomic_bool queuddigitslock;
259
+ uint8_t dtmfsendcount;
261
260
  uint16_t lastdtmfsn;
262
261
 
263
262
  boost::posix_time::ptime tickstarttime;