sip-lab 1.28.12 → 1.29.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.
Files changed (37) hide show
  1. package/DEV.md +55 -0
  2. package/README.md +8 -2
  3. package/binding.gyp +1 -0
  4. package/index.js +7 -0
  5. package/package.json +1 -1
  6. package/prebuilds/linux-x64/node.abi102.node +0 -0
  7. package/prebuilds/linux-x64/node.abi108.node +0 -0
  8. package/prebuilds/linux-x64/node.abi111.node +0 -0
  9. package/prebuilds/linux-x64/node.abi115.node +0 -0
  10. package/prebuilds/linux-x64/node.abi120.node +0 -0
  11. package/prebuilds/linux-x64/node.abi88.node +0 -0
  12. package/prebuilds/linux-x64/node.abi93.node +0 -0
  13. package/samples/100_calls.js +4 -0
  14. package/samples/16_audio_streams.js +2 -0
  15. package/samples/183_session_progress.js +2 -0
  16. package/samples/delayed_media.js +2 -0
  17. package/samples/four_audio_streams_two_refused.js +7 -4
  18. package/samples/mrcp_and_audio.simplified_media.js +2 -0
  19. package/samples/multiple_audio_streams.js +2 -0
  20. package/samples/refuse_telephone_event.js +3 -0
  21. package/samples/reinvite_and_dtmf.js +3 -0
  22. package/samples/reinvite_audio_audio.js +2 -0
  23. package/samples/reinvite_with_hold_unhold.js +2 -0
  24. package/samples/rtp_and_srtp.js +3 -0
  25. package/samples/rtp_and_srtp.rtp_refused.js +3 -0
  26. package/samples/srtp.js +3 -0
  27. package/samples/tcp.js +2 -0
  28. package/samples/text_to_speech.js +3 -0
  29. package/samples/two_audio_streams.js +4 -0
  30. package/samples/two_audio_streams.port_zero.js +4 -0
  31. package/src/addon.cpp +180 -10
  32. package/src/event_templates.cpp +8 -0
  33. package/src/event_templates.hpp +3 -0
  34. package/src/pjmedia/include/pjmedia/bfsk_det.h +25 -0
  35. package/src/pjmedia/src/pjmedia/bfsk_det.c +163 -0
  36. package/src/sip.cpp +520 -21
  37. package/src/sip.hpp +11 -0
package/src/sip.cpp CHANGED
@@ -24,6 +24,7 @@
24
24
  #include "websock.h"
25
25
 
26
26
  #include "dtmfdet.h"
27
+ #include "bfsk_det.h"
27
28
  #include "fax_port.h"
28
29
  #include "flite_port.h"
29
30
  #include "pocketsphinx_port.h"
@@ -266,6 +267,7 @@ int ms_timestamp();
266
267
  bool g_shutting_down;
267
268
 
268
269
  int g_dtmf_inter_digit_timer = 0;
270
+ int g_bfsk_inter_bit_timer = 0;
269
271
 
270
272
  pj_str_t g_sip_ipaddress;
271
273
 
@@ -329,7 +331,8 @@ struct ConfBridgePort {
329
331
  #define FP_FAX 4
330
332
  #define FP_SPEECH_SYNTH 5
331
333
  #define FP_SPEECH_RECOG 6
332
- #define MAX_FP 7
334
+ #define FP_BFSK_DET 7
335
+ #define MAX_FP 8
333
336
 
334
337
  struct AudioEndpoint {
335
338
  pjmedia_transport *med_transport;
@@ -341,6 +344,10 @@ struct AudioEndpoint {
341
344
 
342
345
  pj_str_t mode;
343
346
 
347
+ char BfskBuffer[MAXDIGITS + 1];
348
+ int BfskBufferLength;
349
+ int last_bit_timestamp;
350
+
344
351
  pjmedia_conf *conf;
345
352
  pjmedia_master_port *master_port;
346
353
  pjmedia_port *null_port;
@@ -634,6 +641,7 @@ static void build_stream_stat(ostringstream &oss, pjmedia_rtcp_stat *stat,
634
641
 
635
642
  bool prepare_tonegen(Call *call, AudioEndpoint *ae);
636
643
  bool prepare_dtmfdet(Call *call, AudioEndpoint *ae);
644
+ bool prepare_bfsk_det(Call *call, AudioEndpoint *ae, const int freq_zero, const int freq_one, const int min_level, const int baud_rate);
637
645
  bool prepare_wav_player(Call *call, AudioEndpoint *ae, const char *file, unsigned flags, bool end_of_file_event);
638
646
  bool prepare_wav_writer(Call *call, AudioEndpoint *ae, const char *file);
639
647
  bool prepare_fax(Call *call, AudioEndpoint *ae, bool is_sender, const char *file, unsigned flags);
@@ -659,6 +667,7 @@ pj_status_t audio_endpoint_stop_record_wav(Call *call, AudioEndpoint *ae);
659
667
  pj_status_t audio_endpoint_stop_fax(Call *call, AudioEndpoint *ae);
660
668
  pj_status_t audio_endpoint_stop_speech_synth(Call *call, AudioEndpoint *ae);
661
669
  pj_status_t audio_endpoint_stop_speech_recog(Call *call, AudioEndpoint *ae);
670
+ pj_status_t audio_endpoint_stop_inband_dtmf_detection(Call *call, AudioEndpoint *ae);
662
671
 
663
672
  static pjsip_module mod_tester = {
664
673
  NULL,
@@ -791,13 +800,13 @@ pj_status_t create_audio_endpoint_conf(Call *call, AudioEndpoint *ae, pjmedia_po
791
800
  return PJ_SUCCESS;
792
801
  }
793
802
 
794
- static int find_endpoint_by_inband_dtmf_media_port(Call *call,
795
- pjmedia_port *port) {
803
+ static int find_endpoint_by_media_port(Call *call,
804
+ pjmedia_port *port, int type) {
796
805
  for (int i = 0; i < call->media_count; i++) {
797
806
  MediaEndpoint *me = (MediaEndpoint *)call->media[i];
798
807
  if (ENDPOINT_TYPE_AUDIO == me->type) {
799
808
  AudioEndpoint *ae = (AudioEndpoint *)me->endpoint.audio;
800
- if (ae->feature_cbps[FP_DTMFDET].port && (pjmedia_port *)ae->feature_cbps[FP_DTMFDET].port == port) {
809
+ if (ae->feature_cbps[type].port && (pjmedia_port *)ae->feature_cbps[type].port == port) {
801
810
  return i;
802
811
  }
803
812
  }
@@ -825,7 +834,7 @@ static void on_inband_dtmf(pjmedia_port *port, void *user_data, char digit) {
825
834
 
826
835
  Call *call = (Call *)user_data;
827
836
 
828
- int media_id = find_endpoint_by_inband_dtmf_media_port(call, port);
837
+ int media_id = find_endpoint_by_media_port(call, port, FP_DTMFDET);
829
838
  assert(media_id >= 0);
830
839
 
831
840
  MediaEndpoint *me = (MediaEndpoint *)call->media[media_id];
@@ -855,6 +864,53 @@ static void on_inband_dtmf(pjmedia_port *port, void *user_data, char digit) {
855
864
  }
856
865
  }
857
866
 
867
+ static void on_bfsk_bit(pjmedia_port *port, void *user_data, int bit) {
868
+ printf("on_bfsk_bit: %i\n", bit);
869
+
870
+ if (g_shutting_down)
871
+ return;
872
+
873
+ long call_id;
874
+ if (!g_call_ids.get_id((long)user_data, call_id)) {
875
+ addon_log(
876
+ L_DBG,
877
+ "on_bfsk_bit: Failed to get call_id. Event will not be notified.\n");
878
+ return;
879
+ }
880
+
881
+ Call *call = (Call *)user_data;
882
+
883
+ int media_id = find_endpoint_by_media_port(call, port, FP_BFSK_DET);
884
+ assert(media_id >= 0);
885
+
886
+ MediaEndpoint *me = (MediaEndpoint *)call->media[media_id];
887
+ AudioEndpoint *ae = (AudioEndpoint *)me->endpoint.audio;
888
+
889
+ if (g_bfsk_inter_bit_timer) {
890
+
891
+ PJW_LOCK();
892
+ int len = ae->BfskBufferLength;
893
+
894
+ if (len > MAXDIGITS) {
895
+ PJW_UNLOCK();
896
+ addon_log(L_DBG, "No more space for bits in bfsk buffer\n");
897
+ return;
898
+ }
899
+
900
+ ae->BfskBuffer[len] = bit;
901
+ ae->BfskBufferLength++;
902
+
903
+ ae->last_bit_timestamp = ms_timestamp();
904
+ PJW_UNLOCK();
905
+ } else {
906
+ char evt[1024];
907
+ char the_bit[1];
908
+ the_bit[0] = bit;
909
+ make_evt_bfsk(evt, sizeof(evt), call_id, 1, the_bit, media_id);
910
+ dispatch_event(evt);
911
+ }
912
+ }
913
+
858
914
  static void on_fax_result(pjmedia_port *port, void *user_data, int result) {
859
915
  if (g_shutting_down)
860
916
  return;
@@ -3413,6 +3469,178 @@ out:
3413
3469
  return 0;
3414
3470
  }
3415
3471
 
3472
+ pj_status_t audio_endpoint_send_bfsk(Call *call, AudioEndpoint *ae,
3473
+ const char *bits, const int freq_zero, const int freq_one, const int level, const int baud_rate) {
3474
+ pj_status_t status;
3475
+
3476
+ if (!prepare_tonegen(call, ae)) {
3477
+ set_error("prepare_tonegen failed.");
3478
+ return -1;
3479
+ }
3480
+
3481
+ int len = strlen(bits);
3482
+
3483
+ int duration = 1000 / baud_rate; // Duration of each tone in milliseconds
3484
+
3485
+ pjmedia_tone_desc *tones = (pjmedia_tone_desc*)pj_pool_zalloc(call->inv->pool, sizeof(pjmedia_tone_desc) * len);
3486
+
3487
+ for (int i = 0; i < len; ++i) {
3488
+ tones[i].freq1 = bits[i] == '0' ? freq_zero : freq_one;
3489
+ tones[i].on_msec = duration;
3490
+ tones[i].off_msec = duration;
3491
+ tones[i].volume = level;
3492
+ }
3493
+
3494
+ status = pjmedia_tonegen_play((pjmedia_port *)ae->feature_cbps[FP_TONEGEN].port, len, tones, 0);
3495
+ if (status != PJ_SUCCESS) {
3496
+ set_error("pjmedia_tonegen_plays failed.");
3497
+ return status;
3498
+ }
3499
+
3500
+ return PJ_SUCCESS;
3501
+ }
3502
+
3503
+ pj_status_t send_bfsk(Call *call, const char *bits, const int freq_zero, const int freq_one, const int level, const int baud_rate) {
3504
+ for (int i = 0; i < call->media_count; i++) {
3505
+ MediaEndpoint *me = (MediaEndpoint *)call->media[i];
3506
+ if (me->type != ENDPOINT_TYPE_AUDIO)
3507
+ continue;
3508
+
3509
+ if(me->port == 0)
3510
+ continue;
3511
+
3512
+ AudioEndpoint *ae = (AudioEndpoint *)me->endpoint.audio;
3513
+
3514
+ pj_status_t status = audio_endpoint_send_bfsk(call, ae, bits, freq_zero, freq_one, level, baud_rate);
3515
+ if (status != PJ_SUCCESS)
3516
+ return status;
3517
+ }
3518
+
3519
+ return PJ_SUCCESS;
3520
+ }
3521
+
3522
+ int pjw_call_send_bfsk(long call_id, const char *json) {
3523
+ #define BITS_MAX_LEN 32 // pjmedia_tonegen limit
3524
+
3525
+ PJW_LOCK();
3526
+ clear_error();
3527
+
3528
+ Call *call;
3529
+
3530
+ pj_status_t status;
3531
+
3532
+ long val;
3533
+
3534
+ int len;
3535
+
3536
+ char *bits;
3537
+ int freq_zero;
3538
+ int freq_one;
3539
+ int level;
3540
+ int baud_rate;
3541
+
3542
+ MediaEndpoint *me;
3543
+ AudioEndpoint *ae;
3544
+ int res;
3545
+
3546
+ int media_id = -1;
3547
+
3548
+ char buffer[MAX_JSON_INPUT];
3549
+
3550
+ Document document;
3551
+
3552
+ const char *valid_params[] = {"bits", "freq_zero", "freq_one", "level", "baud_rate", "media_id", ""};
3553
+
3554
+ if (!g_call_ids.get(call_id, val)) {
3555
+ set_error("Invalid call_id");
3556
+ goto out;
3557
+ }
3558
+ call = (Call *)val;
3559
+
3560
+ if (!parse_json(document, json, buffer, MAX_JSON_INPUT)) {
3561
+ goto out;
3562
+ }
3563
+
3564
+ if (!validate_params(document, valid_params)) {
3565
+ goto out;
3566
+ }
3567
+
3568
+ if (json_get_string_param(document, "bits", false, &bits) <= 0) {
3569
+ goto out;
3570
+ }
3571
+
3572
+ if (json_get_int_param(document, "freq_zero", false, &freq_zero) <= 0) {
3573
+ goto out;
3574
+ }
3575
+
3576
+ if (json_get_int_param(document, "freq_one", false, &freq_one) <= 0) {
3577
+ goto out;
3578
+ }
3579
+
3580
+ if (json_get_int_param(document, "level", false, &level) <= 0) {
3581
+ goto out;
3582
+ }
3583
+
3584
+ if (json_get_int_param(document, "baud_rate", false, &baud_rate) <= 0) {
3585
+ goto out;
3586
+ }
3587
+
3588
+ len = strlen(bits);
3589
+
3590
+ if (len > BITS_MAX_LEN) {
3591
+ set_error("bits too long");
3592
+ goto out;
3593
+ }
3594
+
3595
+ for (int i = 0; i < len; ++i) {
3596
+ if (bits[i] != '0' && bits[i] != '1') {
3597
+ set_error("Invalid character");
3598
+ goto out;
3599
+ }
3600
+ }
3601
+
3602
+ res = json_get_int_param(document, "media_id", true, &media_id);
3603
+ if (res <= 0) {
3604
+ goto out;
3605
+ }
3606
+
3607
+ if (NOT_FOUND_OPTIONAL == res) {
3608
+ // send_bfsk_bits to all audio endpoints
3609
+ status = send_bfsk(call, bits, freq_zero, freq_one, level, baud_rate);
3610
+ if (status != PJ_SUCCESS) {
3611
+ goto out;
3612
+ }
3613
+ } else {
3614
+ // send_bfsk_bits to specified media_id
3615
+
3616
+ if (media_id >= call->media_count) {
3617
+ set_error("invalid media_id");
3618
+ goto out;
3619
+ }
3620
+
3621
+ me = (MediaEndpoint *)call->media[media_id];
3622
+ if (ENDPOINT_TYPE_AUDIO != me->type) {
3623
+ set_error("invalid media_id non audio");
3624
+ goto out;
3625
+ }
3626
+
3627
+ ae = (AudioEndpoint *)me->endpoint.audio;
3628
+
3629
+ status = audio_endpoint_send_bfsk(call, ae, bits, freq_one, freq_zero, level, baud_rate);
3630
+ if (status != PJ_SUCCESS) {
3631
+ goto out;
3632
+ }
3633
+ }
3634
+
3635
+ out:
3636
+ PJW_UNLOCK();
3637
+ if (pjw_errorstring[0]) {
3638
+ return -1;
3639
+ }
3640
+
3641
+ return 0;
3642
+ }
3643
+
3416
3644
  pj_status_t audio_endpoint_remove_port(Call *call, AudioEndpoint *ae, ConfBridgePort *cbp) {
3417
3645
  printf("audio_endpoint_remove_port\n");
3418
3646
  pj_status_t status;
@@ -4253,6 +4481,229 @@ out:
4253
4481
  return 0;
4254
4482
  }
4255
4483
 
4484
+ pj_status_t audio_endpoint_start_inband_dtmf_detection(Call *call, AudioEndpoint *ae) {
4485
+ pj_status_t status;
4486
+
4487
+ if(!ae->stream_cbp.port) {
4488
+ set_error("stream port is not ready yet");
4489
+ return -1;
4490
+ }
4491
+
4492
+ if(!prepare_dtmfdet(call, ae)) {
4493
+ return -1;
4494
+ }
4495
+
4496
+ return PJ_SUCCESS;
4497
+ }
4498
+
4499
+ int pjw_call_start_inband_dtmf_detection(long call_id, const char *json) {
4500
+ printf("pjw_call_start_inband_dtmf_detection\n");
4501
+ PJW_LOCK();
4502
+ clear_error();
4503
+
4504
+ long val;
4505
+ Call *call;
4506
+
4507
+ pj_status_t status;
4508
+
4509
+ MediaEndpoint *me;
4510
+ AudioEndpoint *ae;
4511
+ int ae_count;
4512
+ int res;
4513
+
4514
+ int media_id = -1;
4515
+
4516
+ char buffer[MAX_JSON_INPUT];
4517
+
4518
+ Document document;
4519
+
4520
+ const char *valid_params[] = {"media_id", ""};
4521
+
4522
+ if (!g_call_ids.get(call_id, val)) {
4523
+ set_error("Invalid call_id");
4524
+ goto out;
4525
+ }
4526
+ call = (Call *)val;
4527
+
4528
+ ae_count = count_media_by_type(call, ENDPOINT_TYPE_AUDIO);
4529
+
4530
+ if (ae_count == 0) {
4531
+ set_error("No audio endpoint");
4532
+ goto out;
4533
+ }
4534
+
4535
+ if (!parse_json(document, json, buffer, MAX_JSON_INPUT)) {
4536
+ goto out;
4537
+ }
4538
+
4539
+ if (!validate_params(document, valid_params)) {
4540
+ goto out;
4541
+ }
4542
+
4543
+ res = json_get_int_param(document, "media_id", true, &media_id);
4544
+ if (res <= 0) {
4545
+ goto out;
4546
+ }
4547
+
4548
+ if (NOT_FOUND_OPTIONAL == res) {
4549
+ for (int i = 0; i < call->media_count; i++) {
4550
+ MediaEndpoint *me = (MediaEndpoint *)call->media[i];
4551
+ if (me->type == ENDPOINT_TYPE_AUDIO) {
4552
+ AudioEndpoint *ae = (AudioEndpoint *)me->endpoint.audio;
4553
+ status = audio_endpoint_start_inband_dtmf_detection(call, ae);
4554
+ if (status != PJ_SUCCESS) goto out;
4555
+ }
4556
+ }
4557
+ } else {
4558
+ if ((int)media_id >= call->media_count) {
4559
+ set_error("invalid media_id");
4560
+ goto out;
4561
+ }
4562
+
4563
+ me = (MediaEndpoint *)call->media[media_id];
4564
+ if (ENDPOINT_TYPE_AUDIO != me->type) {
4565
+ set_error("media_endpoint is not audio endpoint");
4566
+ goto out;
4567
+ }
4568
+
4569
+ ae = (AudioEndpoint *)me->endpoint.audio;
4570
+
4571
+ audio_endpoint_start_inband_dtmf_detection(call, ae);
4572
+ }
4573
+
4574
+ out:
4575
+ PJW_UNLOCK();
4576
+ if (pjw_errorstring[0]) {
4577
+ return -1;
4578
+ }
4579
+
4580
+ return 0;
4581
+ }
4582
+
4583
+ pj_status_t audio_endpoint_start_bfsk_detection(Call *call, AudioEndpoint *ae, const int freq_zero, const int freq_one, const int min_level, const int baud_rate) {
4584
+ pj_status_t status;
4585
+
4586
+ if(!ae->stream_cbp.port) {
4587
+ set_error("stream port is not ready yet");
4588
+ return -1;
4589
+ }
4590
+
4591
+ if(!prepare_bfsk_det(call, ae, freq_zero, freq_one, min_level, baud_rate)) {
4592
+ return -1;
4593
+ }
4594
+
4595
+ return PJ_SUCCESS;
4596
+ }
4597
+
4598
+ int pjw_call_start_bfsk_detection(long call_id, const char *json) {
4599
+ printf("pjw_call_start_bfsk_detection\n");
4600
+ PJW_LOCK();
4601
+ clear_error();
4602
+
4603
+ long val;
4604
+ Call *call;
4605
+
4606
+ pj_status_t status;
4607
+
4608
+ MediaEndpoint *me;
4609
+ AudioEndpoint *ae;
4610
+ int ae_count;
4611
+ int res;
4612
+
4613
+ int media_id = -1;
4614
+
4615
+ int freq_zero;
4616
+ int freq_one;
4617
+ int min_level;
4618
+ int baud_rate;
4619
+
4620
+ char buffer[MAX_JSON_INPUT];
4621
+
4622
+ Document document;
4623
+
4624
+ const char *valid_params[] = {"freq_zero", "freq_one", "min_level", "baud_rate", "media_id", ""};
4625
+
4626
+ if (!g_call_ids.get(call_id, val)) {
4627
+ set_error("Invalid call_id");
4628
+ goto out;
4629
+ }
4630
+ call = (Call *)val;
4631
+
4632
+ ae_count = count_media_by_type(call, ENDPOINT_TYPE_AUDIO);
4633
+
4634
+ if (ae_count == 0) {
4635
+ set_error("No audio endpoint");
4636
+ goto out;
4637
+ }
4638
+
4639
+ if (!parse_json(document, json, buffer, MAX_JSON_INPUT)) {
4640
+ goto out;
4641
+ }
4642
+
4643
+ if (!validate_params(document, valid_params)) {
4644
+ goto out;
4645
+ }
4646
+
4647
+ res = json_get_int_param(document, "freq_zero", false, &freq_zero);
4648
+ if (res <= 0) {
4649
+ goto out;
4650
+ }
4651
+
4652
+ res = json_get_int_param(document, "freq_one", false, &freq_one);
4653
+ if (res <= 0) {
4654
+ goto out;
4655
+ }
4656
+
4657
+ res = json_get_int_param(document, "min_level", false, &min_level);
4658
+ if (res <= 0) {
4659
+ goto out;
4660
+ }
4661
+
4662
+ res = json_get_int_param(document, "baud_rate", false, &baud_rate);
4663
+ if (res <= 0) {
4664
+ goto out;
4665
+ }
4666
+
4667
+ res = json_get_int_param(document, "media_id", true, &media_id);
4668
+ if (res <= 0) {
4669
+ goto out;
4670
+ }
4671
+
4672
+ if (NOT_FOUND_OPTIONAL == res) {
4673
+ for (int i = 0; i < call->media_count; i++) {
4674
+ MediaEndpoint *me = (MediaEndpoint *)call->media[i];
4675
+ if (me->type == ENDPOINT_TYPE_AUDIO) {
4676
+ AudioEndpoint *ae = (AudioEndpoint *)me->endpoint.audio;
4677
+ status = audio_endpoint_start_bfsk_detection(call, ae, freq_zero, freq_one, min_level, baud_rate);
4678
+ if (status != PJ_SUCCESS) goto out;
4679
+ }
4680
+ }
4681
+ } else {
4682
+ if ((int)media_id >= call->media_count) {
4683
+ set_error("invalid media_id");
4684
+ goto out;
4685
+ }
4686
+
4687
+ me = (MediaEndpoint *)call->media[media_id];
4688
+ if (ENDPOINT_TYPE_AUDIO != me->type) {
4689
+ set_error("media_endpoint is not audio endpoint");
4690
+ goto out;
4691
+ }
4692
+
4693
+ ae = (AudioEndpoint *)me->endpoint.audio;
4694
+
4695
+ audio_endpoint_start_bfsk_detection(call, ae, freq_zero, freq_one, min_level, baud_rate);
4696
+ }
4697
+
4698
+ out:
4699
+ PJW_UNLOCK();
4700
+ if (pjw_errorstring[0]) {
4701
+ return -1;
4702
+ }
4703
+
4704
+ return 0;
4705
+ }
4706
+
4256
4707
  pj_status_t call_stop_op_on_all_audio_endpoints(Call *call,
4257
4708
  audio_endpoint_stop_op_t op) {
4258
4709
  addon_log(L_DBG, "call_stop_op_on_audio_endpoints media_count=%d\n",
@@ -4274,6 +4725,7 @@ pj_status_t call_stop_op_on_all_audio_endpoints(Call *call,
4274
4725
  return PJ_SUCCESS;
4275
4726
  }
4276
4727
 
4728
+
4277
4729
  int audio_endpoint_stop_op(long call_id, const char *json, audio_endpoint_stop_op_t op) {
4278
4730
  PJW_LOCK();
4279
4731
  clear_error();
@@ -4362,6 +4814,14 @@ pj_status_t audio_endpoint_stop_speech_recog(Call *call, AudioEndpoint *ae) {
4362
4814
  return audio_endpoint_remove_port(call, ae, &ae->feature_cbps[FP_SPEECH_RECOG]);
4363
4815
  }
4364
4816
 
4817
+ pj_status_t audio_endpoint_stop_inband_dtmf_detection(Call *call, AudioEndpoint *ae) {
4818
+ return audio_endpoint_remove_port(call, ae, &ae->feature_cbps[FP_DTMFDET]);
4819
+ }
4820
+
4821
+ pj_status_t audio_endpoint_stop_bfsk_detection(Call *call, AudioEndpoint *ae) {
4822
+ return audio_endpoint_remove_port(call, ae, &ae->feature_cbps[FP_BFSK_DET]);
4823
+ }
4824
+
4365
4825
 
4366
4826
  int pjw_call_stop_play_wav(long call_id, const char *json) {
4367
4827
  return audio_endpoint_stop_op(call_id, json, audio_endpoint_stop_play_wav);
@@ -4383,6 +4843,11 @@ int pjw_call_stop_speech_recog(long call_id, const char *json) {
4383
4843
  return audio_endpoint_stop_op(call_id, json, audio_endpoint_stop_speech_recog);
4384
4844
  }
4385
4845
 
4846
+ int pjw_call_stop_inband_dtmf_detection(long call_id, const char *json) {
4847
+ return audio_endpoint_stop_op(call_id, json, audio_endpoint_stop_inband_dtmf_detection);
4848
+ }
4849
+
4850
+
4386
4851
 
4387
4852
  int pjw_call_start_fax(long call_id, const char *json) {
4388
4853
  PJW_LOCK();
@@ -5030,14 +5495,6 @@ bool restart_media_stream(Call *call, MediaEndpoint *me,
5030
5495
  dispatch_event(evt);
5031
5496
  return false;
5032
5497
  }
5033
-
5034
- // we always add dtmfdet to audio endpoints
5035
- if(!prepare_dtmfdet(call, ae)) {
5036
- make_evt_media_update(evt, sizeof(evt), call->id,
5037
- "setup_failed (prepare_dtmfdet failed)", "");
5038
- dispatch_event(evt);
5039
- return false;
5040
- }
5041
5498
  } else if(
5042
5499
  (PJMEDIA_PIA_SRATE(&old_port->info) != PJMEDIA_PIA_SRATE(&new_port->info)) ||
5043
5500
  (PJMEDIA_PIA_CCNT(&old_port->info) != PJMEDIA_PIA_CCNT(&new_port->info)) ||
@@ -5065,14 +5522,6 @@ bool restart_media_stream(Call *call, MediaEndpoint *me,
5065
5522
  return false;
5066
5523
  }
5067
5524
 
5068
- // we always add dtmfdet to audio endpoints
5069
- if(!prepare_dtmfdet(call, ae)) {
5070
- make_evt_media_update(evt, sizeof(evt), call->id,
5071
- "setup_failed (prepare_dtmfdet failed)", "");
5072
- dispatch_event(evt);
5073
- return false;
5074
- }
5075
-
5076
5525
  // at this point we could try to recreate ports (see #91)
5077
5526
  } else {
5078
5527
  printf("call_id=%i restart_media_stream: stream characteristics no change\n", call->id);
@@ -7006,10 +7455,16 @@ bool prepare_wav_writer(Call *call, AudioEndpoint *ae, const char *file) {
7006
7455
  }
7007
7456
 
7008
7457
  bool prepare_dtmfdet(Call *call, AudioEndpoint *ae) {
7458
+ printf("DEBUG prepare_dtmfdet\n");
7009
7459
  pj_status_t status;
7010
7460
 
7011
7461
  ConfBridgePort *fp = &ae->feature_cbps[FP_DTMFDET];
7012
7462
 
7463
+ if(fp->port) {
7464
+ printf("already prepared\n");
7465
+ return true;
7466
+ }
7467
+
7013
7468
  status = pjmedia_dtmfdet_create(
7014
7469
  call->inv->pool,
7015
7470
  PJMEDIA_PIA_SRATE(&ae->stream_cbp.port->info),
@@ -7033,6 +7488,41 @@ bool prepare_dtmfdet(Call *call, AudioEndpoint *ae) {
7033
7488
  return connect_feature_port_to_stream_port(call, ae, fp);
7034
7489
  }
7035
7490
 
7491
+ bool prepare_bfsk_det(Call *call, AudioEndpoint *ae, const int freq_zero, const int freq_one, const int min_level, const int baud_rate) {
7492
+ printf("DEBUG prepare_bfsk_det\n");
7493
+ pj_status_t status;
7494
+
7495
+ ConfBridgePort *fp = &ae->feature_cbps[FP_BFSK_DET];
7496
+
7497
+ if(fp->port) {
7498
+ printf("already prepared\n");
7499
+ return true;
7500
+ }
7501
+
7502
+ status = pjmedia_bfsk_det_create(
7503
+ call->inv->pool,
7504
+ PJMEDIA_PIA_SRATE(&ae->stream_cbp.port->info),
7505
+ PJMEDIA_PIA_CCNT(&ae->stream_cbp.port->info),
7506
+ PJMEDIA_PIA_SPF(&ae->stream_cbp.port->info),
7507
+ PJMEDIA_PIA_BITS(&ae->stream_cbp.port->info),
7508
+ on_bfsk_bit, call, freq_zero, freq_one, min_level, baud_rate, &fp->port);
7509
+ if (status != PJ_SUCCESS) {
7510
+ set_error("pjmedia_bfsk_det_create failed");
7511
+ return false;
7512
+ }
7513
+
7514
+ status = pjmedia_conf_add_port(ae->conf, call->inv->pool, fp->port, NULL, &fp->slot);
7515
+ if (status != PJ_SUCCESS) {
7516
+ set_error("pjmedia_conf_add_port failed");
7517
+ return false;
7518
+ }
7519
+
7520
+ fp->connection_mode = CONNECTION_MODE_SINK;
7521
+
7522
+ return connect_feature_port_to_stream_port(call, ae, fp);
7523
+ }
7524
+
7525
+
7036
7526
  bool prepare_fax(Call *call, AudioEndpoint *ae, bool is_sender, const char *file, unsigned flags) {
7037
7527
  pj_status_t status;
7038
7528
 
@@ -8616,6 +9106,15 @@ void check_digit_buffer(Call *call, int mode) {
8616
9106
  *pLen = 0;
8617
9107
  ae->last_digit_timestamp[mode] = 0;
8618
9108
  }
9109
+
9110
+ if (ae->last_bit_timestamp > 0 &&
9111
+ g_now - ae->last_bit_timestamp > g_bfsk_inter_bit_timer) {
9112
+ int len = ae->BfskBufferLength;
9113
+ ae->BfskBufferLength = 0;
9114
+ make_evt_bfsk(evt, sizeof(evt), call->id, len, ae->BfskBuffer, i);
9115
+ dispatch_event(evt);
9116
+ ae->last_bit_timestamp = 0;
9117
+ }
8619
9118
  }
8620
9119
  }
8621
9120
 
package/src/sip.hpp CHANGED
@@ -41,6 +41,8 @@ int pjw_call_terminate(long call_id, const char *json);
41
41
 
42
42
  int pjw_call_send_dtmf(long call_id, const char *json);
43
43
 
44
+ int pjw_call_send_bfsk(long call_id, const char *json);
45
+
44
46
  int pjw_call_reinvite(long call_id, const char *json);
45
47
 
46
48
  int pjw_call_send_request(long call_id, const char *json);
@@ -64,6 +66,15 @@ int pjw_call_stop_speech_synth(long call_id, const char *json);
64
66
  int pjw_call_start_speech_recog(long call_id, const char *json);
65
67
 
66
68
  int pjw_call_stop_speech_recog(long call_id, const char *json);
69
+
70
+ int pjw_call_start_inband_dtmf_detection(long call_id, const char *json);
71
+
72
+ int pjw_call_stop_inband_dtmf_detection(long call_id, const char *json);
73
+
74
+ int pjw_call_start_bfsk_detection(long call_id, const char *json);
75
+
76
+ int pjw_call_stop_bfsk_detection(long call_id, const char *json);
77
+
67
78
  int pjw_call_get_stream_stat(long call_id, const char *json, char *out_stats);
68
79
 
69
80
  // int pjw_call_refer(long call_id, const char *json, long