sip-lab 1.23.0 → 1.24.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.
- package/README.md +3 -3
- package/binding.gyp +4 -0
- package/build_deps.sh +19 -0
- package/index.js +18 -0
- package/package.json +3 -2
- package/pocketsphinx/model/CMakeLists.txt +3 -0
- package/pocketsphinx/model/en-us/cmudict-en-us.dict +134782 -0
- package/pocketsphinx/model/en-us/en-us/README +34 -0
- package/pocketsphinx/model/en-us/en-us/feat.params +12 -0
- package/pocketsphinx/model/en-us/en-us/mdef +0 -0
- package/pocketsphinx/model/en-us/en-us/means +0 -0
- package/pocketsphinx/model/en-us/en-us/noisedict +5 -0
- package/pocketsphinx/model/en-us/en-us/sendump +0 -0
- package/pocketsphinx/model/en-us/en-us/transition_matrices +0 -0
- package/pocketsphinx/model/en-us/en-us/variances +0 -0
- package/pocketsphinx/model/en-us/en-us-phone.lm.bin +0 -0
- package/pocketsphinx/model/en-us/en-us.lm.bin +0 -0
- package/prebuilds/linux-x64/sip-lab.node +0 -0
- package/samples/artifacts/hello_good_morning.wav +0 -0
- package/samples/play_wav_and_speech_recog.bad_transcript.pcmu8000.js +182 -0
- package/samples/speech_synth_and_recog.speex16000.js +186 -0
- package/samples/tcp_and_extra_headers.js +44 -1
- package/src/addon.cpp +37 -0
- package/src/event_templates.cpp +6 -0
- package/src/event_templates.hpp +2 -0
- package/src/pjmedia/include/pjmedia/pocketsphinx_port.h +19 -0
- package/src/pjmedia/src/pjmedia/flite_port.c +4 -7
- package/src/pjmedia/src/pjmedia/pocketsphinx_port.c +169 -46
- package/src/sip.cpp +398 -273
- package/src/sip.hpp +3 -0
package/src/sip.cpp
CHANGED
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
#include "dtmfdet.h"
|
|
24
24
|
#include "fax_port.h"
|
|
25
25
|
#include "flite_port.h"
|
|
26
|
+
#include "pocketsphinx_port.h"
|
|
26
27
|
|
|
27
28
|
#include <ctime>
|
|
28
29
|
|
|
@@ -265,14 +266,6 @@ pjsip_route_hdr route_set;
|
|
|
265
266
|
pjsip_route_hdr *route;
|
|
266
267
|
const pj_str_t hname = pj_str((char *)"Route");
|
|
267
268
|
|
|
268
|
-
#define CONF_PORTS 1024
|
|
269
|
-
//#define CLOCK_RATE 16000
|
|
270
|
-
#define CLOCK_RATE 8000
|
|
271
|
-
#define CHANNEL_COUNT 1
|
|
272
|
-
#define PTIME 20
|
|
273
|
-
#define SAMPLES_PER_FRAME (CLOCK_RATE*PTIME/1000)
|
|
274
|
-
#define BITS_PER_SAMPLE 16
|
|
275
|
-
|
|
276
269
|
#define MAXDIGITS 256
|
|
277
270
|
|
|
278
271
|
#define DTMF_MODE_RFC2833 0
|
|
@@ -324,6 +317,10 @@ struct AudioEndpoint {
|
|
|
324
317
|
|
|
325
318
|
pj_str_t mode;
|
|
326
319
|
|
|
320
|
+
pjmedia_conf *conf;
|
|
321
|
+
pjmedia_master_port *master_port;
|
|
322
|
+
pjmedia_port *null_port;
|
|
323
|
+
|
|
327
324
|
ConfBridgePort stream_cbp;
|
|
328
325
|
ConfBridgePort wav_player_cbp;
|
|
329
326
|
ConfBridgePort wav_writer_cbp;
|
|
@@ -331,6 +328,7 @@ struct AudioEndpoint {
|
|
|
331
328
|
ConfBridgePort dtmfdet_cbp;
|
|
332
329
|
ConfBridgePort fax_cbp;
|
|
333
330
|
ConfBridgePort flite_cbp;
|
|
331
|
+
ConfBridgePort pocketsphinx_cbp;
|
|
334
332
|
};
|
|
335
333
|
|
|
336
334
|
struct VideoEndpoint {
|
|
@@ -433,10 +431,6 @@ struct Call {
|
|
|
433
431
|
pjmedia_sdp_session *active_remote_sdp;
|
|
434
432
|
|
|
435
433
|
bool local_sdp_answer_already_set;
|
|
436
|
-
|
|
437
|
-
pjmedia_conf *conf;
|
|
438
|
-
pjmedia_master_port *master_port;
|
|
439
|
-
pjmedia_port *null_port;
|
|
440
434
|
};
|
|
441
435
|
|
|
442
436
|
#define MAX_TCP_DATA 4096
|
|
@@ -472,6 +466,10 @@ PackageSet g_PackageSet;
|
|
|
472
466
|
|
|
473
467
|
#define DEFAULT_EXPIRES 600
|
|
474
468
|
|
|
469
|
+
#define CONNECTION_MODE_SOURCE 0
|
|
470
|
+
#define CONNECTION_MODE_SINK 1
|
|
471
|
+
#define CONNECTION_MODE_SOURCE_AND_SINK 2
|
|
472
|
+
|
|
475
473
|
void handle_events() {
|
|
476
474
|
pj_time_val tv = {0, 1};
|
|
477
475
|
pjsip_endpt_handle_events(g_sip_endpt, &tv);
|
|
@@ -618,23 +616,23 @@ static void build_stream_stat(ostringstream &oss, pjmedia_rtcp_stat *stat,
|
|
|
618
616
|
|
|
619
617
|
bool prepare_tonegen(Call *call, AudioEndpoint *ae);
|
|
620
618
|
bool prepare_dtmfdet(Call *call, AudioEndpoint *ae);
|
|
621
|
-
bool prepare_wav_player(Call *
|
|
622
|
-
bool prepare_wav_writer(Call *
|
|
623
|
-
bool prepare_fax(Call *
|
|
624
|
-
|
|
625
|
-
bool
|
|
619
|
+
bool prepare_wav_player(Call *call, AudioEndpoint *ae, const char *file, unsigned flags, bool end_of_file_event);
|
|
620
|
+
bool prepare_wav_writer(Call *call, AudioEndpoint *ae, const char *file);
|
|
621
|
+
bool prepare_fax(Call *call, AudioEndpoint *ae, bool is_sender, const char *file, unsigned flags);
|
|
622
|
+
bool prepare_flite(Call *call, AudioEndpoint *ae, const char *voice, bool end_of_speech_event);
|
|
623
|
+
bool prepare_pocketsphinx(Call *call, AudioEndpoint *ae);
|
|
626
624
|
|
|
627
625
|
void prepare_error_event(ostringstream *oss, char *scope, char *details);
|
|
628
626
|
// void prepare_pjsipcall_error_event(ostringstream *oss, char *scope, char
|
|
629
627
|
// *function, pj_status_t s);
|
|
630
628
|
void append_status(ostringstream *oss, pj_status_t s);
|
|
631
629
|
|
|
632
|
-
bool is_media_active(Call *
|
|
630
|
+
bool is_media_active(Call *call, MediaEndpoint *me);
|
|
633
631
|
void close_media_endpoint(Call *call, MediaEndpoint *me);
|
|
634
632
|
|
|
635
|
-
void close_media(Call *
|
|
633
|
+
void close_media(Call *call);
|
|
636
634
|
|
|
637
|
-
bool process_media(Call *
|
|
635
|
+
bool process_media(Call *call, pjsip_dialog *dlg, Document &document, bool answer);
|
|
638
636
|
|
|
639
637
|
typedef pj_status_t (*audio_endpoint_stop_op_t)(Call *call, AudioEndpoint *ae);
|
|
640
638
|
|
|
@@ -642,6 +640,7 @@ pj_status_t audio_endpoint_stop_play_wav(Call *call, AudioEndpoint *ae);
|
|
|
642
640
|
pj_status_t audio_endpoint_stop_record_wav(Call *call, AudioEndpoint *ae);
|
|
643
641
|
pj_status_t audio_endpoint_stop_fax(Call *call, AudioEndpoint *ae);
|
|
644
642
|
pj_status_t audio_endpoint_stop_speech_synth(Call *call, AudioEndpoint *ae);
|
|
643
|
+
pj_status_t audio_endpoint_stop_speech_recog(Call *call, AudioEndpoint *ae);
|
|
645
644
|
|
|
646
645
|
static pjsip_module mod_tester = {
|
|
647
646
|
NULL,
|
|
@@ -716,23 +715,36 @@ find_endpoint_by_inband_dtmf_media_stream(Call *call,
|
|
|
716
715
|
return -1;
|
|
717
716
|
}
|
|
718
717
|
|
|
719
|
-
pj_status_t
|
|
718
|
+
pj_status_t create_audio_endpoint_conf(Call *call, AudioEndpoint *ae, pjmedia_port *stream_port) {
|
|
720
719
|
pj_status_t status;
|
|
720
|
+
int conf_ports = 16;
|
|
721
|
+
|
|
722
|
+
unsigned sampling_rate = PJMEDIA_PIA_SRATE(&stream_port->info);
|
|
723
|
+
unsigned channel_count = PJMEDIA_PIA_CCNT(&stream_port->info);
|
|
724
|
+
unsigned samples_per_frame = PJMEDIA_PIA_SPF(&stream_port->info);
|
|
725
|
+
unsigned bits_per_sample = PJMEDIA_PIA_BITS(&stream_port->info);
|
|
726
|
+
|
|
721
727
|
status = pjmedia_conf_create(call->inv->pool,
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
728
|
+
conf_ports,
|
|
729
|
+
sampling_rate,
|
|
730
|
+
channel_count,
|
|
731
|
+
samples_per_frame,
|
|
732
|
+
bits_per_sample,
|
|
727
733
|
PJMEDIA_CONF_NO_DEVICE,
|
|
728
|
-
&
|
|
734
|
+
&ae->conf);
|
|
729
735
|
|
|
730
736
|
if (status != PJ_SUCCESS) {
|
|
731
737
|
addon_log(L_DBG, "pjmedia_conf_create failed\n");
|
|
732
738
|
return false;
|
|
733
739
|
}
|
|
734
740
|
|
|
735
|
-
status = pjmedia_null_port_create(
|
|
741
|
+
status = pjmedia_null_port_create(
|
|
742
|
+
call->inv->pool,
|
|
743
|
+
sampling_rate,
|
|
744
|
+
channel_count,
|
|
745
|
+
samples_per_frame,
|
|
746
|
+
bits_per_sample,
|
|
747
|
+
&ae->null_port);
|
|
736
748
|
if (status != PJ_SUCCESS) {
|
|
737
749
|
addon_log(L_DBG, "pjmedia_null_port_created failed\n");
|
|
738
750
|
return false;
|
|
@@ -740,19 +752,19 @@ pj_status_t setup_call_conf(Call *call) {
|
|
|
740
752
|
|
|
741
753
|
pjmedia_port *conf_port = NULL;
|
|
742
754
|
|
|
743
|
-
conf_port = pjmedia_conf_get_master_port(
|
|
755
|
+
conf_port = pjmedia_conf_get_master_port(ae->conf);
|
|
744
756
|
if (conf_port == NULL) {
|
|
745
757
|
addon_log(L_DBG, "pjmedia_conf_get_master_port failed\n");
|
|
746
758
|
return false;
|
|
747
759
|
}
|
|
748
760
|
|
|
749
|
-
status = pjmedia_master_port_create(call->inv->pool,
|
|
761
|
+
status = pjmedia_master_port_create(call->inv->pool, ae->null_port, conf_port, 0, &ae->master_port);
|
|
750
762
|
if (status != PJ_SUCCESS) {
|
|
751
763
|
addon_log(L_DBG, "pjmedia_master_port_create failed\n");
|
|
752
764
|
return false;
|
|
753
765
|
}
|
|
754
766
|
|
|
755
|
-
status = pjmedia_master_port_start(
|
|
767
|
+
status = pjmedia_master_port_start(ae->master_port);
|
|
756
768
|
if (status != PJ_SUCCESS) {
|
|
757
769
|
addon_log(L_DBG, "pjmedia_master_port_start failed\n");
|
|
758
770
|
return false;
|
|
@@ -761,38 +773,6 @@ pj_status_t setup_call_conf(Call *call) {
|
|
|
761
773
|
return PJ_SUCCESS;
|
|
762
774
|
}
|
|
763
775
|
|
|
764
|
-
void release_call_conf(Call *call) {
|
|
765
|
-
pj_status_t status;
|
|
766
|
-
|
|
767
|
-
if (call->master_port) {
|
|
768
|
-
status = pjmedia_master_port_stop(call->master_port);
|
|
769
|
-
if(status != PJ_SUCCESS) {
|
|
770
|
-
addon_log(L_DBG, "pjmedia_master_port_stop failed\n");
|
|
771
|
-
}
|
|
772
|
-
pjmedia_master_port_destroy(call->master_port, 0);
|
|
773
|
-
if(status != PJ_SUCCESS) {
|
|
774
|
-
addon_log(L_DBG, "pjmedia_master_port_destroy failed\n");
|
|
775
|
-
}
|
|
776
|
-
call->master_port = NULL;
|
|
777
|
-
}
|
|
778
|
-
|
|
779
|
-
if (call->conf) {
|
|
780
|
-
status = pjmedia_conf_destroy(call->conf);
|
|
781
|
-
if(status != PJ_SUCCESS) {
|
|
782
|
-
addon_log(L_DBG, "pjmedia_conf_destroy failed\n");
|
|
783
|
-
}
|
|
784
|
-
call->conf = NULL;
|
|
785
|
-
}
|
|
786
|
-
|
|
787
|
-
if (call->null_port) {
|
|
788
|
-
status = pjmedia_port_destroy(call->null_port);
|
|
789
|
-
if(status != PJ_SUCCESS) {
|
|
790
|
-
addon_log(L_DBG, "pjmedia_port_destroy(null_port) failed\n");
|
|
791
|
-
}
|
|
792
|
-
call->null_port = NULL;
|
|
793
|
-
}
|
|
794
|
-
}
|
|
795
|
-
|
|
796
776
|
static int find_endpoint_by_inband_dtmf_media_port(Call *call,
|
|
797
777
|
pjmedia_port *port) {
|
|
798
778
|
for (int i = 0; i < call->media_count; i++) {
|
|
@@ -905,6 +885,22 @@ static void on_end_of_speech(pjmedia_port *port, void *user_data) {
|
|
|
905
885
|
dispatch_event(evt);
|
|
906
886
|
}
|
|
907
887
|
|
|
888
|
+
static void on_speech_transcript(pjmedia_port*, void *user_data, char* transcript) {
|
|
889
|
+
if (g_shutting_down)
|
|
890
|
+
return;
|
|
891
|
+
|
|
892
|
+
long call_id;
|
|
893
|
+
if (!g_call_ids.get_id((long)user_data, call_id)) {
|
|
894
|
+
addon_log(
|
|
895
|
+
L_DBG,
|
|
896
|
+
"on_speech_transcript: Failed to get call_id. Event will not be notified.\n");
|
|
897
|
+
return;
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
char evt[1024];
|
|
901
|
+
make_evt_speech_transcript(evt, sizeof(evt), call_id, transcript);
|
|
902
|
+
dispatch_event(evt);
|
|
903
|
+
}
|
|
908
904
|
|
|
909
905
|
void dispatch_event(const char *evt) {
|
|
910
906
|
addon_log(L_DBG, "dispach_event called with evt=%s\n", evt);
|
|
@@ -3047,12 +3043,6 @@ int call_create(Transport *t, unsigned flags, pjsip_dialog *dlg,
|
|
|
3047
3043
|
}
|
|
3048
3044
|
// addon_log(L_DBG, "pjsip_dlg_add_usage OK\n");
|
|
3049
3045
|
|
|
3050
|
-
status = setup_call_conf(call);
|
|
3051
|
-
if (status != PJ_SUCCESS) {
|
|
3052
|
-
set_error("setup_call_conf failed");
|
|
3053
|
-
return -1;
|
|
3054
|
-
}
|
|
3055
|
-
|
|
3056
3046
|
return call_id;
|
|
3057
3047
|
}
|
|
3058
3048
|
|
|
@@ -3251,7 +3241,7 @@ out:
|
|
|
3251
3241
|
return 0;
|
|
3252
3242
|
}
|
|
3253
3243
|
|
|
3254
|
-
pj_status_t audio_endpoint_remove_port(Call *call, ConfBridgePort *cbp) {
|
|
3244
|
+
pj_status_t audio_endpoint_remove_port(Call *call, AudioEndpoint *ae, ConfBridgePort *cbp) {
|
|
3255
3245
|
printf("audio_endpoint_remove_port\n");
|
|
3256
3246
|
pj_status_t status;
|
|
3257
3247
|
|
|
@@ -3262,7 +3252,7 @@ pj_status_t audio_endpoint_remove_port(Call *call, ConfBridgePort *cbp) {
|
|
|
3262
3252
|
pjmedia_conf_disconnect_port_from_sinks(conf, port);
|
|
3263
3253
|
*/
|
|
3264
3254
|
|
|
3265
|
-
status = pjmedia_conf_remove_port(
|
|
3255
|
+
status = pjmedia_conf_remove_port(ae->conf, cbp->slot);
|
|
3266
3256
|
if (status != PJ_SUCCESS) {
|
|
3267
3257
|
set_error("pjmedia_conf_remove_port failed");
|
|
3268
3258
|
return false;
|
|
@@ -3928,6 +3918,121 @@ out:
|
|
|
3928
3918
|
return 0;
|
|
3929
3919
|
}
|
|
3930
3920
|
|
|
3921
|
+
pj_status_t audio_endpoint_start_speech_recog(Call *call, AudioEndpoint *ae) {
|
|
3922
|
+
pj_status_t status;
|
|
3923
|
+
|
|
3924
|
+
if(!ae->stream_cbp.port) {
|
|
3925
|
+
set_error("stream port is not ready yet");
|
|
3926
|
+
return -1;
|
|
3927
|
+
}
|
|
3928
|
+
|
|
3929
|
+
// First stop and destroy existing port.
|
|
3930
|
+
status = audio_endpoint_stop_speech_recog(call, ae);
|
|
3931
|
+
if(status != PJ_SUCCESS) {
|
|
3932
|
+
return -1;
|
|
3933
|
+
}
|
|
3934
|
+
|
|
3935
|
+
if (!prepare_pocketsphinx(call, ae)) {
|
|
3936
|
+
return -1;
|
|
3937
|
+
}
|
|
3938
|
+
|
|
3939
|
+
return PJ_SUCCESS;
|
|
3940
|
+
}
|
|
3941
|
+
|
|
3942
|
+
int pjw_call_start_speech_recog(long call_id, const char *json) {
|
|
3943
|
+
PJW_LOCK();
|
|
3944
|
+
clear_error();
|
|
3945
|
+
|
|
3946
|
+
long val;
|
|
3947
|
+
Call *call;
|
|
3948
|
+
|
|
3949
|
+
pj_status_t status;
|
|
3950
|
+
|
|
3951
|
+
MediaEndpoint *me;
|
|
3952
|
+
AudioEndpoint *ae;
|
|
3953
|
+
int ae_count;
|
|
3954
|
+
int res;
|
|
3955
|
+
|
|
3956
|
+
int media_id = -1;
|
|
3957
|
+
|
|
3958
|
+
char *voice;
|
|
3959
|
+
|
|
3960
|
+
char *text;
|
|
3961
|
+
|
|
3962
|
+
bool end_of_speech_event = false;
|
|
3963
|
+
|
|
3964
|
+
unsigned flags = 0;
|
|
3965
|
+
|
|
3966
|
+
bool no_loop = false;
|
|
3967
|
+
|
|
3968
|
+
char buffer[MAX_JSON_INPUT];
|
|
3969
|
+
|
|
3970
|
+
Document document;
|
|
3971
|
+
|
|
3972
|
+
const char *valid_params[] = {"media_id", ""};
|
|
3973
|
+
|
|
3974
|
+
if (!g_call_ids.get(call_id, val)) {
|
|
3975
|
+
set_error("Invalid call_id");
|
|
3976
|
+
goto out;
|
|
3977
|
+
}
|
|
3978
|
+
call = (Call *)val;
|
|
3979
|
+
|
|
3980
|
+
ae_count = count_media_by_type(call, ENDPOINT_TYPE_AUDIO);
|
|
3981
|
+
|
|
3982
|
+
if (ae_count == 0) {
|
|
3983
|
+
set_error("No audio endpoint");
|
|
3984
|
+
goto out;
|
|
3985
|
+
}
|
|
3986
|
+
|
|
3987
|
+
if (!parse_json(document, json, buffer, MAX_JSON_INPUT)) {
|
|
3988
|
+
goto out;
|
|
3989
|
+
}
|
|
3990
|
+
|
|
3991
|
+
if (!validate_params(document, valid_params)) {
|
|
3992
|
+
goto out;
|
|
3993
|
+
}
|
|
3994
|
+
|
|
3995
|
+
res = json_get_int_param(document, "media_id", true, &media_id);
|
|
3996
|
+
if (res <= 0) {
|
|
3997
|
+
goto out;
|
|
3998
|
+
}
|
|
3999
|
+
|
|
4000
|
+
if (NOT_FOUND_OPTIONAL == res) {
|
|
4001
|
+
// start on all audio media endpoints
|
|
4002
|
+
for (int i = 0; i < call->media_count; i++) {
|
|
4003
|
+
MediaEndpoint *me = (MediaEndpoint *)call->media[i];
|
|
4004
|
+
if (me->type == ENDPOINT_TYPE_AUDIO) {
|
|
4005
|
+
AudioEndpoint *ae = (AudioEndpoint *)me->endpoint.audio;
|
|
4006
|
+
status = audio_endpoint_start_speech_recog(call, ae);
|
|
4007
|
+
if (status != PJ_SUCCESS) goto out;
|
|
4008
|
+
}
|
|
4009
|
+
}
|
|
4010
|
+
} else {
|
|
4011
|
+
if ((int)media_id >= call->media_count) {
|
|
4012
|
+
set_error("invalid media_id");
|
|
4013
|
+
goto out;
|
|
4014
|
+
}
|
|
4015
|
+
|
|
4016
|
+
me = (MediaEndpoint *)call->media[media_id];
|
|
4017
|
+
if (ENDPOINT_TYPE_AUDIO != me->type) {
|
|
4018
|
+
set_error("media_endpoint is not audio endpoint");
|
|
4019
|
+
goto out;
|
|
4020
|
+
}
|
|
4021
|
+
|
|
4022
|
+
ae = (AudioEndpoint *)me->endpoint.audio;
|
|
4023
|
+
|
|
4024
|
+
audio_endpoint_start_speech_recog(call, ae);
|
|
4025
|
+
}
|
|
4026
|
+
|
|
4027
|
+
out:
|
|
4028
|
+
PJW_UNLOCK();
|
|
4029
|
+
if (pjw_errorstring[0]) {
|
|
4030
|
+
return -1;
|
|
4031
|
+
}
|
|
4032
|
+
|
|
4033
|
+
return 0;
|
|
4034
|
+
}
|
|
4035
|
+
|
|
3931
4036
|
pj_status_t call_stop_op_on_all_audio_endpoints(Call *call,
|
|
3932
4037
|
audio_endpoint_stop_op_t op) {
|
|
3933
4038
|
addon_log(L_DBG, "call_stop_op_on_audio_endpoints media_count=%d\n",
|
|
@@ -4018,19 +4123,23 @@ out:
|
|
|
4018
4123
|
}
|
|
4019
4124
|
|
|
4020
4125
|
pj_status_t audio_endpoint_stop_speech_synth(Call *call, AudioEndpoint *ae) {
|
|
4021
|
-
return audio_endpoint_remove_port(call, &ae->flite_cbp);
|
|
4126
|
+
return audio_endpoint_remove_port(call, ae, &ae->flite_cbp);
|
|
4127
|
+
}
|
|
4128
|
+
|
|
4129
|
+
pj_status_t audio_endpoint_stop_speech_recog(Call *call, AudioEndpoint *ae) {
|
|
4130
|
+
return audio_endpoint_remove_port(call, ae, &ae->pocketsphinx_cbp);
|
|
4022
4131
|
}
|
|
4023
4132
|
|
|
4024
4133
|
pj_status_t audio_endpoint_stop_play_wav(Call *call, AudioEndpoint *ae) {
|
|
4025
|
-
return audio_endpoint_remove_port(call, &ae->wav_player_cbp);
|
|
4134
|
+
return audio_endpoint_remove_port(call, ae, &ae->wav_player_cbp);
|
|
4026
4135
|
}
|
|
4027
4136
|
|
|
4028
4137
|
pj_status_t audio_endpoint_stop_record_wav(Call *call, AudioEndpoint *ae) {
|
|
4029
|
-
return audio_endpoint_remove_port(call, &ae->wav_writer_cbp);
|
|
4138
|
+
return audio_endpoint_remove_port(call, ae, &ae->wav_writer_cbp);
|
|
4030
4139
|
}
|
|
4031
4140
|
|
|
4032
4141
|
pj_status_t audio_endpoint_stop_fax(Call *call, AudioEndpoint *ae) {
|
|
4033
|
-
return audio_endpoint_remove_port(call, &ae->fax_cbp);
|
|
4142
|
+
return audio_endpoint_remove_port(call, ae, &ae->fax_cbp);
|
|
4034
4143
|
}
|
|
4035
4144
|
|
|
4036
4145
|
|
|
@@ -4039,6 +4148,10 @@ int pjw_call_stop_speech_synth(long call_id, const char *json) {
|
|
|
4039
4148
|
return audio_endpoint_stop_op(call_id, json, audio_endpoint_stop_speech_synth);
|
|
4040
4149
|
}
|
|
4041
4150
|
|
|
4151
|
+
int pjw_call_stop_speech_recog(long call_id, const char *json) {
|
|
4152
|
+
return audio_endpoint_stop_op(call_id, json, audio_endpoint_stop_speech_recog);
|
|
4153
|
+
}
|
|
4154
|
+
|
|
4042
4155
|
int pjw_call_stop_play_wav(long call_id, const char *json) {
|
|
4043
4156
|
return audio_endpoint_stop_op(call_id, json, audio_endpoint_stop_play_wav);
|
|
4044
4157
|
}
|
|
@@ -4523,82 +4636,80 @@ bool start_tcp_media(Call *call, MediaEndpoint *me,
|
|
|
4523
4636
|
return true;
|
|
4524
4637
|
}
|
|
4525
4638
|
|
|
4639
|
+
void close_audio_endpoint_ports_and_conf(Call *call, AudioEndpoint *ae) {
|
|
4640
|
+
pj_status_t status;
|
|
4526
4641
|
|
|
4527
|
-
|
|
4528
|
-
|
|
4529
|
-
|
|
4530
|
-
|
|
4531
|
-
|
|
4532
|
-
|
|
4533
|
-
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
|
|
4541
|
-
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4642
|
+
audio_endpoint_remove_port(call, ae, &ae->stream_cbp);
|
|
4643
|
+
audio_endpoint_remove_port(call, ae, &ae->wav_player_cbp);
|
|
4644
|
+
audio_endpoint_remove_port(call, ae, &ae->wav_writer_cbp);
|
|
4645
|
+
audio_endpoint_remove_port(call, ae, &ae->tonegen_cbp);
|
|
4646
|
+
audio_endpoint_remove_port(call, ae, &ae->dtmfdet_cbp);
|
|
4647
|
+
audio_endpoint_remove_port(call, ae, &ae->fax_cbp);
|
|
4648
|
+
audio_endpoint_remove_port(call, ae, &ae->flite_cbp);
|
|
4649
|
+
audio_endpoint_remove_port(call, ae, &ae->pocketsphinx_cbp);
|
|
4650
|
+
|
|
4651
|
+
if (ae->master_port) {
|
|
4652
|
+
status = pjmedia_master_port_stop(ae->master_port);
|
|
4653
|
+
if(status != PJ_SUCCESS) {
|
|
4654
|
+
addon_log(L_DBG, "pjmedia_master_port_stop failed\n");
|
|
4655
|
+
}
|
|
4656
|
+
pjmedia_master_port_destroy(ae->master_port, 0);
|
|
4657
|
+
if(status != PJ_SUCCESS) {
|
|
4658
|
+
addon_log(L_DBG, "pjmedia_master_port_destroy failed\n");
|
|
4659
|
+
}
|
|
4660
|
+
ae->master_port = NULL;
|
|
4546
4661
|
}
|
|
4547
4662
|
|
|
4548
|
-
if(ae->
|
|
4549
|
-
|
|
4550
|
-
|
|
4551
|
-
|
|
4552
|
-
|
|
4553
|
-
|
|
4554
|
-
return false;
|
|
4555
|
-
}
|
|
4663
|
+
if (ae->conf) {
|
|
4664
|
+
status = pjmedia_conf_destroy(ae->conf);
|
|
4665
|
+
if(status != PJ_SUCCESS) {
|
|
4666
|
+
addon_log(L_DBG, "pjmedia_conf_destroy failed\n");
|
|
4667
|
+
}
|
|
4668
|
+
ae->conf = NULL;
|
|
4556
4669
|
}
|
|
4557
4670
|
|
|
4558
|
-
if(ae->
|
|
4559
|
-
|
|
4560
|
-
|
|
4561
|
-
|
|
4562
|
-
|
|
4563
|
-
|
|
4564
|
-
return false;
|
|
4565
|
-
}
|
|
4671
|
+
if (ae->null_port) {
|
|
4672
|
+
status = pjmedia_port_destroy(ae->null_port);
|
|
4673
|
+
if(status != PJ_SUCCESS) {
|
|
4674
|
+
addon_log(L_DBG, "pjmedia_port_destroy(null_port) failed\n");
|
|
4675
|
+
}
|
|
4676
|
+
ae->null_port = NULL;
|
|
4566
4677
|
}
|
|
4678
|
+
}
|
|
4567
4679
|
|
|
4568
|
-
|
|
4569
|
-
|
|
4570
|
-
if (status != PJ_SUCCESS) {
|
|
4571
|
-
make_evt_media_update(evt, sizeof(evt), call->id,
|
|
4572
|
-
"setup_failed (pjmedia_conf_disconnect_port fax dst failed)", "");
|
|
4573
|
-
dispatch_event(evt);
|
|
4574
|
-
return false;
|
|
4575
|
-
}
|
|
4576
|
-
|
|
4577
|
-
status = pjmedia_conf_disconnect_port(call->conf, ae->fax_cbp.slot, ae->stream_cbp.slot);
|
|
4578
|
-
if (status != PJ_SUCCESS) {
|
|
4579
|
-
make_evt_media_update(evt, sizeof(evt), call->id,
|
|
4580
|
-
"setup_failed (pjmedia_conf_disconnect_port for fax src failed)", "");
|
|
4581
|
-
dispatch_event(evt);
|
|
4582
|
-
return false;
|
|
4583
|
-
}
|
|
4584
|
-
}
|
|
4680
|
+
bool connect_feature_port_to_stream_port(Call *call, AudioEndpoint *ae, ConfBridgePort *cbp, int connection_mode) {
|
|
4681
|
+
pj_status_t status;
|
|
4585
4682
|
|
|
4586
|
-
|
|
4683
|
+
if(connection_mode == CONNECTION_MODE_SOURCE || connection_mode == CONNECTION_MODE_SOURCE_AND_SINK) {
|
|
4684
|
+
status = pjmedia_conf_connect_port(ae->conf, cbp->slot, ae->stream_cbp.slot, 0);
|
|
4587
4685
|
if (status != PJ_SUCCESS) {
|
|
4588
|
-
|
|
4589
|
-
"setup_failed (pjmedia_conf_remove_port failed)", "");
|
|
4686
|
+
set_error("pjmedia_conf_connect_port failed");
|
|
4590
4687
|
return false;
|
|
4591
4688
|
}
|
|
4592
|
-
|
|
4593
|
-
|
|
4594
|
-
status =
|
|
4689
|
+
}
|
|
4690
|
+
if(connection_mode == CONNECTION_MODE_SINK || connection_mode == CONNECTION_MODE_SOURCE_AND_SINK) {
|
|
4691
|
+
status = pjmedia_conf_connect_port(ae->conf, ae->stream_cbp.slot, cbp->slot, 0);
|
|
4692
|
+
printf("status=%i\n" ,status);
|
|
4595
4693
|
if (status != PJ_SUCCESS) {
|
|
4596
|
-
|
|
4597
|
-
"setup_failed (pjmedia_port_destroy failed)", "");
|
|
4694
|
+
set_error("pjmedia_conf_connect_port failed");
|
|
4598
4695
|
return false;
|
|
4599
4696
|
}
|
|
4600
|
-
|
|
4601
|
-
|
|
4697
|
+
}
|
|
4698
|
+
return true;
|
|
4699
|
+
}
|
|
4700
|
+
|
|
4701
|
+
bool restart_media_stream(Call *call, MediaEndpoint *me,
|
|
4702
|
+
const pjmedia_sdp_session *local_sdp,
|
|
4703
|
+
const pjmedia_sdp_session *remote_sdp, int idx) {
|
|
4704
|
+
char evt[4096];
|
|
4705
|
+
pjmedia_stream_info stream_info;
|
|
4706
|
+
|
|
4707
|
+
AudioEndpoint *ae = (AudioEndpoint *)me->endpoint.audio;
|
|
4708
|
+
|
|
4709
|
+
pj_status_t status;
|
|
4710
|
+
|
|
4711
|
+
pjmedia_port *old_port = ae->stream_cbp.port;
|
|
4712
|
+
pjmedia_port *new_port;
|
|
4602
4713
|
|
|
4603
4714
|
status =
|
|
4604
4715
|
pjmedia_stream_info_from_sdp(&stream_info, call->inv->dlg->pool,
|
|
@@ -4664,7 +4775,7 @@ bool restart_media_stream(Call *call, MediaEndpoint *me,
|
|
|
4664
4775
|
return false;
|
|
4665
4776
|
}
|
|
4666
4777
|
|
|
4667
|
-
status = pjmedia_stream_get_port(ae->med_stream, &
|
|
4778
|
+
status = pjmedia_stream_get_port(ae->med_stream, &new_port);
|
|
4668
4779
|
if (status != PJ_SUCCESS) {
|
|
4669
4780
|
make_evt_media_update(evt, sizeof(evt), call->id,
|
|
4670
4781
|
"setup_failed (pjmedia_stream_get_port failed)", "");
|
|
@@ -4672,73 +4783,112 @@ bool restart_media_stream(Call *call, MediaEndpoint *me,
|
|
|
4672
4783
|
return false;
|
|
4673
4784
|
}
|
|
4674
4785
|
|
|
4675
|
-
|
|
4676
|
-
|
|
4677
|
-
|
|
4678
|
-
|
|
4679
|
-
dispatch_event(evt);
|
|
4680
|
-
return false;
|
|
4681
|
-
}
|
|
4682
|
-
|
|
4683
|
-
if(!ae->dtmfdet_cbp.port) {
|
|
4684
|
-
if(!prepare_dtmfdet(call, ae)) {
|
|
4786
|
+
if(!old_port) {
|
|
4787
|
+
printf("call_id=%i restart_media_stream !old_port (first SDP negotiation)\n", call->id);
|
|
4788
|
+
status = create_audio_endpoint_conf(call, ae, new_port);
|
|
4789
|
+
if (status != PJ_SUCCESS) {
|
|
4685
4790
|
make_evt_media_update(evt, sizeof(evt), call->id,
|
|
4686
|
-
"setup_failed (
|
|
4791
|
+
"setup_failed (create_audio_endpoint_conf failed)", "");
|
|
4687
4792
|
dispatch_event(evt);
|
|
4688
4793
|
return false;
|
|
4689
4794
|
}
|
|
4690
|
-
}
|
|
4691
4795
|
|
|
4692
|
-
|
|
4693
|
-
status =
|
|
4796
|
+
ae->stream_cbp.port = new_port;
|
|
4797
|
+
status = pjmedia_conf_add_port(ae->conf, call->inv->pool, ae->stream_cbp.port, NULL, &ae->stream_cbp.slot);
|
|
4694
4798
|
if (status != PJ_SUCCESS) {
|
|
4695
4799
|
make_evt_media_update(evt, sizeof(evt), call->id,
|
|
4696
|
-
"setup_failed (
|
|
4800
|
+
"setup_failed (pjmedia_conf_add_port failed)", "");
|
|
4697
4801
|
dispatch_event(evt);
|
|
4698
4802
|
return false;
|
|
4699
4803
|
}
|
|
4700
|
-
}
|
|
4701
4804
|
|
|
4702
|
-
|
|
4703
|
-
|
|
4704
|
-
if (status != PJ_SUCCESS) {
|
|
4805
|
+
// we always add dtmfdet to audio endpoints
|
|
4806
|
+
if(!prepare_dtmfdet(call, ae)) {
|
|
4705
4807
|
make_evt_media_update(evt, sizeof(evt), call->id,
|
|
4706
|
-
|
|
4808
|
+
"setup_failed (prepare_dtmfdet failed)", "");
|
|
4707
4809
|
dispatch_event(evt);
|
|
4708
4810
|
return false;
|
|
4709
4811
|
}
|
|
4710
|
-
}
|
|
4711
|
-
|
|
4712
|
-
|
|
4713
|
-
|
|
4812
|
+
} else if(
|
|
4813
|
+
(PJMEDIA_PIA_SRATE(&old_port->info) != PJMEDIA_PIA_SRATE(&new_port->info)) ||
|
|
4814
|
+
(PJMEDIA_PIA_CCNT(&old_port->info) != PJMEDIA_PIA_CCNT(&new_port->info)) ||
|
|
4815
|
+
(PJMEDIA_PIA_SPF(&old_port->info) != PJMEDIA_PIA_SPF(&new_port->info)) ||
|
|
4816
|
+
(PJMEDIA_PIA_BITS(&old_port->info) != PJMEDIA_PIA_BITS(&new_port->info))) {
|
|
4817
|
+
// stream characteristics changed so we need to destroy old conf and ports
|
|
4818
|
+
printf("call_id=%i restart_media_stream: stream characteristics changed\n", call->id);
|
|
4819
|
+
close_audio_endpoint_ports_and_conf(call, ae);
|
|
4820
|
+
|
|
4821
|
+
// then create a new conf
|
|
4822
|
+
status = create_audio_endpoint_conf(call, ae, new_port);
|
|
4714
4823
|
if (status != PJ_SUCCESS) {
|
|
4715
4824
|
make_evt_media_update(evt, sizeof(evt), call->id,
|
|
4716
|
-
"setup_failed (
|
|
4825
|
+
"setup_failed (create_audio_endpoint_conf failed)", "");
|
|
4717
4826
|
dispatch_event(evt);
|
|
4718
4827
|
return false;
|
|
4719
|
-
|
|
4720
4828
|
}
|
|
4721
|
-
}
|
|
4722
4829
|
|
|
4723
|
-
|
|
4724
|
-
status =
|
|
4830
|
+
ae->stream_cbp.port = new_port;
|
|
4831
|
+
status = pjmedia_conf_add_port(ae->conf, call->inv->pool, ae->stream_cbp.port, NULL, &ae->stream_cbp.slot);
|
|
4725
4832
|
if (status != PJ_SUCCESS) {
|
|
4726
4833
|
make_evt_media_update(evt, sizeof(evt), call->id,
|
|
4727
|
-
"setup_failed (
|
|
4834
|
+
"setup_failed (pjmedia_conf_add_port failed)", "");
|
|
4728
4835
|
dispatch_event(evt);
|
|
4729
4836
|
return false;
|
|
4837
|
+
}
|
|
4730
4838
|
|
|
4839
|
+
// we always add dtmfdet to audio endpoints
|
|
4840
|
+
if(!prepare_dtmfdet(call, ae)) {
|
|
4841
|
+
make_evt_media_update(evt, sizeof(evt), call->id,
|
|
4842
|
+
"setup_failed (prepare_dtmfdet failed)", "");
|
|
4843
|
+
dispatch_event(evt);
|
|
4844
|
+
return false;
|
|
4731
4845
|
}
|
|
4732
4846
|
|
|
4733
|
-
|
|
4847
|
+
// at this point we could try to recreate ports (see #91)
|
|
4848
|
+
} else {
|
|
4849
|
+
printf("call_id=%i restart_media_stream: stream characteristics no change\n", call->id);
|
|
4850
|
+
// stream characteristics didn't change so just replace the stream port
|
|
4851
|
+
|
|
4852
|
+
audio_endpoint_remove_port(call, ae, &ae->stream_cbp);
|
|
4853
|
+
ae->stream_cbp.port = new_port;
|
|
4854
|
+
status = pjmedia_conf_add_port(ae->conf, call->inv->pool, ae->stream_cbp.port, NULL, &ae->stream_cbp.slot);
|
|
4734
4855
|
if (status != PJ_SUCCESS) {
|
|
4735
4856
|
make_evt_media_update(evt, sizeof(evt), call->id,
|
|
4736
|
-
"setup_failed (
|
|
4857
|
+
"setup_failed (pjmedia_conf_add_port failed)", "");
|
|
4737
4858
|
dispatch_event(evt);
|
|
4738
4859
|
return false;
|
|
4739
4860
|
}
|
|
4740
|
-
}
|
|
4741
4861
|
|
|
4862
|
+
// Need to connect ports to new stream port
|
|
4863
|
+
if(ae->dtmfdet_cbp.port) {
|
|
4864
|
+
if(!connect_feature_port_to_stream_port(call, ae, &ae->dtmfdet_cbp, CONNECTION_MODE_SINK)) return false;
|
|
4865
|
+
}
|
|
4866
|
+
|
|
4867
|
+
if(ae->wav_writer_cbp.port) {
|
|
4868
|
+
if(!connect_feature_port_to_stream_port(call, ae, &ae->wav_writer_cbp, CONNECTION_MODE_SINK)) return false;
|
|
4869
|
+
}
|
|
4870
|
+
|
|
4871
|
+
if(ae->wav_player_cbp.port) {
|
|
4872
|
+
if(!connect_feature_port_to_stream_port(call, ae, &ae->wav_player_cbp, CONNECTION_MODE_SOURCE)) return false;
|
|
4873
|
+
}
|
|
4874
|
+
|
|
4875
|
+
if(ae->tonegen_cbp.port) {
|
|
4876
|
+
if(!connect_feature_port_to_stream_port(call, ae, &ae->tonegen_cbp, CONNECTION_MODE_SOURCE)) return false;
|
|
4877
|
+
}
|
|
4878
|
+
|
|
4879
|
+
if(ae->fax_cbp.port) {
|
|
4880
|
+
if(!connect_feature_port_to_stream_port(call, ae, &ae->fax_cbp, CONNECTION_MODE_SOURCE_AND_SINK)) return false;
|
|
4881
|
+
}
|
|
4882
|
+
|
|
4883
|
+
if(ae->flite_cbp.port) {
|
|
4884
|
+
if(!connect_feature_port_to_stream_port(call, ae, &ae->flite_cbp, CONNECTION_MODE_SOURCE)) return false;
|
|
4885
|
+
}
|
|
4886
|
+
|
|
4887
|
+
if(ae->pocketsphinx_cbp.port) {
|
|
4888
|
+
if(!connect_feature_port_to_stream_port(call, ae, &ae->pocketsphinx_cbp, CONNECTION_MODE_SINK)) return false;
|
|
4889
|
+
}
|
|
4890
|
+
}
|
|
4891
|
+
|
|
4742
4892
|
return true;
|
|
4743
4893
|
}
|
|
4744
4894
|
|
|
@@ -4925,8 +5075,6 @@ static void on_state_changed(pjsip_inv_session *inv, pjsip_event *e) {
|
|
|
4925
5075
|
}
|
|
4926
5076
|
}
|
|
4927
5077
|
|
|
4928
|
-
release_call_conf(call);
|
|
4929
|
-
|
|
4930
5078
|
long val;
|
|
4931
5079
|
if (!g_call_ids.remove(call_id, val)) {
|
|
4932
5080
|
addon_log(L_DBG, "g_call_ids.remove failed\n");
|
|
@@ -5317,13 +5465,6 @@ static pj_bool_t on_rx_request(pjsip_rx_data *rdata) {
|
|
|
5317
5465
|
return PJ_TRUE;
|
|
5318
5466
|
}
|
|
5319
5467
|
|
|
5320
|
-
status = setup_call_conf(call);
|
|
5321
|
-
if (status != PJ_SUCCESS) {
|
|
5322
|
-
printf("setup_call_conf failed\n");
|
|
5323
|
-
pjsip_endpt_respond_stateless(g_sip_endpt, rdata, 500, &reason, NULL, NULL);
|
|
5324
|
-
return PJ_TRUE;
|
|
5325
|
-
}
|
|
5326
|
-
|
|
5327
5468
|
// TODO: check if this is really necessary as we are calling
|
|
5328
5469
|
// pjsip_dlg_add_usage subsequently
|
|
5329
5470
|
inv->dlg->mod_data[mod_tester.id] = call;
|
|
@@ -6511,10 +6652,10 @@ bool process_media(Call *call, pjsip_dialog *dlg, Document &document, bool answe
|
|
|
6511
6652
|
return true;
|
|
6512
6653
|
}
|
|
6513
6654
|
|
|
6514
|
-
bool is_media_active(Call *
|
|
6655
|
+
bool is_media_active(Call *call, MediaEndpoint *me) {
|
|
6515
6656
|
// check if media from call->media_neg is on call->media
|
|
6516
|
-
for (int i = 0; i <
|
|
6517
|
-
if (me ==
|
|
6657
|
+
for (int i = 0; i < call->media_count; ++i) {
|
|
6658
|
+
if (me == call->media[i])
|
|
6518
6659
|
return true;
|
|
6519
6660
|
}
|
|
6520
6661
|
return false;
|
|
@@ -6522,19 +6663,14 @@ bool is_media_active(Call *c, MediaEndpoint *me) {
|
|
|
6522
6663
|
|
|
6523
6664
|
void close_media_endpoint(Call *call, MediaEndpoint *me) {
|
|
6524
6665
|
printf("close_media_endpoint %p\n", (void*)me);
|
|
6666
|
+
|
|
6667
|
+
pj_status_t status;
|
|
6668
|
+
|
|
6525
6669
|
if(!me) return;
|
|
6526
6670
|
|
|
6527
6671
|
if (ENDPOINT_TYPE_AUDIO == me->type) {
|
|
6528
6672
|
AudioEndpoint *ae = (AudioEndpoint *)me->endpoint.audio;
|
|
6529
|
-
|
|
6530
|
-
audio_endpoint_remove_port(call, &ae->stream_cbp);
|
|
6531
|
-
audio_endpoint_remove_port(call, &ae->wav_player_cbp);
|
|
6532
|
-
audio_endpoint_remove_port(call, &ae->wav_writer_cbp);
|
|
6533
|
-
audio_endpoint_remove_port(call, &ae->tonegen_cbp);
|
|
6534
|
-
audio_endpoint_remove_port(call, &ae->dtmfdet_cbp);
|
|
6535
|
-
audio_endpoint_remove_port(call, &ae->fax_cbp);
|
|
6536
|
-
audio_endpoint_remove_port(call, &ae->flite_cbp);
|
|
6537
|
-
|
|
6673
|
+
close_audio_endpoint_ports_and_conf(call, ae);
|
|
6538
6674
|
close_media_transport(ae->med_transport);
|
|
6539
6675
|
ae->med_transport = NULL;
|
|
6540
6676
|
} else if (ENDPOINT_TYPE_MRCP == me->type) {
|
|
@@ -6558,17 +6694,17 @@ void close_media_endpoint(Call *call, MediaEndpoint *me) {
|
|
|
6558
6694
|
me->port = 0;
|
|
6559
6695
|
}
|
|
6560
6696
|
|
|
6561
|
-
void close_media(Call *
|
|
6562
|
-
printf("close_media call_id=%i\n",
|
|
6563
|
-
for (int i = 0; i <
|
|
6564
|
-
MediaEndpoint *me =
|
|
6565
|
-
close_media_endpoint(
|
|
6697
|
+
void close_media(Call *call) {
|
|
6698
|
+
printf("close_media call_id=%i\n", call->id);
|
|
6699
|
+
for (int i = 0; i < call->media_count; ++i) {
|
|
6700
|
+
MediaEndpoint *me = call->media[i];
|
|
6701
|
+
close_media_endpoint(call, me);
|
|
6566
6702
|
}
|
|
6567
|
-
|
|
6703
|
+
call->media_count = 0;
|
|
6568
6704
|
}
|
|
6569
6705
|
|
|
6570
|
-
bool prepare_tonegen(Call *
|
|
6571
|
-
printf("prepare_tone_gen call.id=%i\n",
|
|
6706
|
+
bool prepare_tonegen(Call *call, AudioEndpoint *ae) {
|
|
6707
|
+
printf("prepare_tone_gen call.id=%i\n", call->id);
|
|
6572
6708
|
pj_status_t status;
|
|
6573
6709
|
|
|
6574
6710
|
if(ae->tonegen_cbp.port) {
|
|
@@ -6577,7 +6713,7 @@ bool prepare_tonegen(Call *c, AudioEndpoint *ae) {
|
|
|
6577
6713
|
}
|
|
6578
6714
|
|
|
6579
6715
|
status = pjmedia_tonegen_create(
|
|
6580
|
-
|
|
6716
|
+
call->inv->pool, PJMEDIA_PIA_SRATE(&ae->stream_cbp.port->info),
|
|
6581
6717
|
PJMEDIA_PIA_CCNT(&ae->stream_cbp.port->info),
|
|
6582
6718
|
PJMEDIA_PIA_SPF(&ae->stream_cbp.port->info),
|
|
6583
6719
|
PJMEDIA_PIA_BITS(&ae->stream_cbp.port->info), 0, &ae->tonegen_cbp.port);
|
|
@@ -6586,22 +6722,16 @@ bool prepare_tonegen(Call *c, AudioEndpoint *ae) {
|
|
|
6586
6722
|
return false;
|
|
6587
6723
|
}
|
|
6588
6724
|
|
|
6589
|
-
status = pjmedia_conf_add_port(
|
|
6725
|
+
status = pjmedia_conf_add_port(ae->conf, call->inv->pool, ae->tonegen_cbp.port, NULL, &ae->tonegen_cbp.slot);
|
|
6590
6726
|
if (status != PJ_SUCCESS) {
|
|
6591
6727
|
set_error("pjmedia_conf_add_port failed");
|
|
6592
6728
|
return false;
|
|
6593
6729
|
}
|
|
6594
6730
|
|
|
6595
|
-
|
|
6596
|
-
if (status != PJ_SUCCESS) {
|
|
6597
|
-
set_error("pjmedia_conf_connect_port failed");
|
|
6598
|
-
return false;
|
|
6599
|
-
}
|
|
6600
|
-
|
|
6601
|
-
return true;
|
|
6731
|
+
return connect_feature_port_to_stream_port(call, ae, &ae->tonegen_cbp, CONNECTION_MODE_SOURCE);
|
|
6602
6732
|
}
|
|
6603
6733
|
|
|
6604
|
-
bool prepare_wav_player(Call *
|
|
6734
|
+
bool prepare_wav_player(Call *call, AudioEndpoint *ae, const char *file, unsigned flags, bool end_of_file_event) {
|
|
6605
6735
|
pj_status_t status;
|
|
6606
6736
|
|
|
6607
6737
|
unsigned wav_ptime;
|
|
@@ -6609,7 +6739,7 @@ bool prepare_wav_player(Call *c, AudioEndpoint *ae, const char *file, unsigned f
|
|
|
6609
6739
|
PJMEDIA_PIA_SRATE(&ae->stream_cbp.port->info);
|
|
6610
6740
|
|
|
6611
6741
|
status = pjmedia_wav_player_port_create(
|
|
6612
|
-
|
|
6742
|
+
call->inv->pool,
|
|
6613
6743
|
file,
|
|
6614
6744
|
wav_ptime,
|
|
6615
6745
|
flags,
|
|
@@ -6623,33 +6753,27 @@ bool prepare_wav_player(Call *c, AudioEndpoint *ae, const char *file, unsigned f
|
|
|
6623
6753
|
}
|
|
6624
6754
|
|
|
6625
6755
|
if (end_of_file_event) {
|
|
6626
|
-
status = pjmedia_wav_player_set_eof_cb2(ae->wav_player_cbp.port, (void*)
|
|
6756
|
+
status = pjmedia_wav_player_set_eof_cb2(ae->wav_player_cbp.port, (void*)call, on_end_of_file);
|
|
6627
6757
|
if (status != PJ_SUCCESS) {
|
|
6628
6758
|
set_error("pjmedia_wav_player_set_eof_cb2 failed");
|
|
6629
6759
|
return false;
|
|
6630
6760
|
}
|
|
6631
6761
|
}
|
|
6632
6762
|
|
|
6633
|
-
status = pjmedia_conf_add_port(
|
|
6763
|
+
status = pjmedia_conf_add_port(ae->conf, call->inv->pool, ae->wav_player_cbp.port, NULL, &ae->wav_player_cbp.slot);
|
|
6634
6764
|
if (status != PJ_SUCCESS) {
|
|
6635
6765
|
set_error("pjmedia_conf_add_port failed");
|
|
6636
6766
|
return false;
|
|
6637
6767
|
}
|
|
6638
6768
|
|
|
6639
|
-
|
|
6640
|
-
if (status != PJ_SUCCESS) {
|
|
6641
|
-
set_error("pjmedia_conf_connect_port failed");
|
|
6642
|
-
return false;
|
|
6643
|
-
}
|
|
6644
|
-
|
|
6645
|
-
return true;
|
|
6769
|
+
return connect_feature_port_to_stream_port(call, ae, &ae->wav_player_cbp, CONNECTION_MODE_SOURCE);
|
|
6646
6770
|
}
|
|
6647
6771
|
|
|
6648
|
-
bool prepare_wav_writer(Call *
|
|
6772
|
+
bool prepare_wav_writer(Call *call, AudioEndpoint *ae, const char *file) {
|
|
6649
6773
|
pj_status_t status;
|
|
6650
6774
|
|
|
6651
6775
|
status = pjmedia_wav_writer_port_create(
|
|
6652
|
-
|
|
6776
|
+
call->inv->pool, file, PJMEDIA_PIA_SRATE(&ae->stream_cbp.port->info),
|
|
6653
6777
|
PJMEDIA_PIA_CCNT(&ae->stream_cbp.port->info), PJMEDIA_PIA_SPF(&ae->stream_cbp.port->info),
|
|
6654
6778
|
PJMEDIA_PIA_BITS(&ae->stream_cbp.port->info), PJMEDIA_FILE_WRITE_PCM, 0,
|
|
6655
6779
|
(pjmedia_port **)&ae->wav_writer_cbp.port);
|
|
@@ -6658,89 +6782,66 @@ bool prepare_wav_writer(Call *c, AudioEndpoint *ae, const char *file) {
|
|
|
6658
6782
|
return false;
|
|
6659
6783
|
}
|
|
6660
6784
|
|
|
6661
|
-
status = pjmedia_conf_add_port(
|
|
6785
|
+
status = pjmedia_conf_add_port(ae->conf, call->inv->pool, ae->wav_writer_cbp.port, NULL, &ae->wav_writer_cbp.slot);
|
|
6662
6786
|
if (status != PJ_SUCCESS) {
|
|
6663
6787
|
set_error("pjmedia_conf_add_port failed");
|
|
6664
6788
|
return false;
|
|
6665
6789
|
}
|
|
6666
6790
|
|
|
6667
|
-
|
|
6668
|
-
if (status != PJ_SUCCESS) {
|
|
6669
|
-
set_error("pjmedia_conf_connect_port failed");
|
|
6670
|
-
return false;
|
|
6671
|
-
}
|
|
6672
|
-
|
|
6673
|
-
return true;
|
|
6791
|
+
return connect_feature_port_to_stream_port(call, ae, &ae->wav_writer_cbp, CONNECTION_MODE_SINK);
|
|
6674
6792
|
}
|
|
6675
6793
|
|
|
6676
|
-
bool prepare_dtmfdet(Call *
|
|
6794
|
+
bool prepare_dtmfdet(Call *call, AudioEndpoint *ae) {
|
|
6677
6795
|
pj_status_t status;
|
|
6678
6796
|
status = pjmedia_dtmfdet_create(
|
|
6679
|
-
|
|
6797
|
+
call->inv->pool,
|
|
6680
6798
|
PJMEDIA_PIA_SRATE(&ae->stream_cbp.port->info),
|
|
6681
|
-
PJMEDIA_PIA_CCNT(&ae->stream_cbp.port->info),
|
|
6799
|
+
PJMEDIA_PIA_CCNT(&ae->stream_cbp.port->info),
|
|
6800
|
+
PJMEDIA_PIA_SPF(&ae->stream_cbp.port->info),
|
|
6682
6801
|
PJMEDIA_PIA_BITS(&ae->stream_cbp.port->info),
|
|
6683
|
-
on_inband_dtmf,
|
|
6802
|
+
on_inband_dtmf, call, &ae->dtmfdet_cbp.port);
|
|
6684
6803
|
if (status != PJ_SUCCESS) {
|
|
6685
6804
|
set_error("pjmedia_dtmfdet_create failed");
|
|
6686
6805
|
return false;
|
|
6687
6806
|
}
|
|
6688
6807
|
|
|
6689
|
-
status = pjmedia_conf_add_port(
|
|
6808
|
+
status = pjmedia_conf_add_port(ae->conf, call->inv->pool, ae->dtmfdet_cbp.port, NULL, &ae->dtmfdet_cbp.slot);
|
|
6690
6809
|
if (status != PJ_SUCCESS) {
|
|
6691
6810
|
set_error("pjmedia_conf_add_port failed");
|
|
6692
6811
|
return false;
|
|
6693
6812
|
}
|
|
6694
6813
|
|
|
6695
|
-
|
|
6696
|
-
if (status != PJ_SUCCESS) {
|
|
6697
|
-
set_error("pjmedia_conf_connect_port failed");
|
|
6698
|
-
return false;
|
|
6699
|
-
}
|
|
6700
|
-
|
|
6701
|
-
return true;
|
|
6814
|
+
return connect_feature_port_to_stream_port(call, ae, &ae->dtmfdet_cbp, CONNECTION_MODE_SINK);
|
|
6702
6815
|
}
|
|
6703
6816
|
|
|
6704
|
-
bool prepare_fax(Call *
|
|
6817
|
+
bool prepare_fax(Call *call, AudioEndpoint *ae, bool is_sender, const char *file,
|
|
6705
6818
|
unsigned flags) {
|
|
6706
6819
|
pj_status_t status;
|
|
6707
6820
|
|
|
6708
6821
|
status = pjmedia_fax_port_create(
|
|
6709
|
-
|
|
6822
|
+
call->inv->pool,
|
|
6710
6823
|
PJMEDIA_PIA_SRATE(&ae->stream_cbp.port->info),
|
|
6711
6824
|
PJMEDIA_PIA_CCNT(&ae->stream_cbp.port->info),
|
|
6712
6825
|
PJMEDIA_PIA_SPF(&ae->stream_cbp.port->info),
|
|
6713
6826
|
PJMEDIA_PIA_BITS(&ae->stream_cbp.port->info),
|
|
6714
|
-
on_fax_result,
|
|
6827
|
+
on_fax_result, call, is_sender, file,
|
|
6715
6828
|
flags, &ae->fax_cbp.port);
|
|
6716
6829
|
if (status != PJ_SUCCESS) {
|
|
6717
6830
|
set_error("pjmedia_fax_port_create failed");
|
|
6718
6831
|
return false;
|
|
6719
6832
|
}
|
|
6720
6833
|
|
|
6721
|
-
status = pjmedia_conf_add_port(
|
|
6834
|
+
status = pjmedia_conf_add_port(ae->conf, call->inv->pool, ae->fax_cbp.port, NULL, &ae->fax_cbp.slot);
|
|
6722
6835
|
if (status != PJ_SUCCESS) {
|
|
6723
6836
|
set_error("pjmedia_conf_add_port failed");
|
|
6724
6837
|
return false;
|
|
6725
6838
|
}
|
|
6726
6839
|
|
|
6727
|
-
|
|
6728
|
-
if (status != PJ_SUCCESS) {
|
|
6729
|
-
set_error("pjmedia_conf_connect_port failed");
|
|
6730
|
-
return false;
|
|
6731
|
-
}
|
|
6732
|
-
|
|
6733
|
-
status = pjmedia_conf_connect_port(c->conf, ae->stream_cbp.slot, ae->fax_cbp.slot, 0);
|
|
6734
|
-
if (status != PJ_SUCCESS) {
|
|
6735
|
-
set_error("pjmedia_conf_connect_port failed");
|
|
6736
|
-
return false;
|
|
6737
|
-
}
|
|
6738
|
-
|
|
6739
|
-
return true;
|
|
6840
|
+
return connect_feature_port_to_stream_port(call, ae, &ae->fax_cbp, CONNECTION_MODE_SOURCE_AND_SINK);
|
|
6740
6841
|
}
|
|
6741
6842
|
|
|
6742
|
-
bool prepare_flite(Call *
|
|
6743
|
-
printf("prepare_flite call.id=%i\n",
|
|
6843
|
+
bool prepare_flite(Call *call, AudioEndpoint *ae, const char *voice, bool end_of_speech_event) {
|
|
6844
|
+
printf("prepare_flite call.id=%i\n", call->id);
|
|
6744
6845
|
pj_status_t status;
|
|
6745
6846
|
|
|
6746
6847
|
if(ae->flite_cbp.port) {
|
|
@@ -6749,7 +6850,7 @@ bool prepare_flite(Call *c, AudioEndpoint *ae, const char *voice, bool end_of_sp
|
|
|
6749
6850
|
}
|
|
6750
6851
|
|
|
6751
6852
|
status = pjmedia_flite_port_create(
|
|
6752
|
-
|
|
6853
|
+
call->inv->pool, PJMEDIA_PIA_SRATE(&ae->stream_cbp.port->info),
|
|
6753
6854
|
PJMEDIA_PIA_CCNT(&ae->stream_cbp.port->info),
|
|
6754
6855
|
PJMEDIA_PIA_SPF(&ae->stream_cbp.port->info),
|
|
6755
6856
|
PJMEDIA_PIA_BITS(&ae->stream_cbp.port->info), voice, &ae->flite_cbp.port);
|
|
@@ -6759,28 +6860,52 @@ bool prepare_flite(Call *c, AudioEndpoint *ae, const char *voice, bool end_of_sp
|
|
|
6759
6860
|
}
|
|
6760
6861
|
|
|
6761
6862
|
if (end_of_speech_event) {
|
|
6762
|
-
status = pjmedia_flite_port_set_eof_cb(ae->flite_cbp.port, (void*)
|
|
6863
|
+
status = pjmedia_flite_port_set_eof_cb(ae->flite_cbp.port, (void*)call, on_end_of_speech);
|
|
6763
6864
|
if (status != PJ_SUCCESS) {
|
|
6764
6865
|
set_error("pjmedia_flite_port_set_eof_cb failed");
|
|
6765
6866
|
return false;
|
|
6766
6867
|
}
|
|
6767
6868
|
}
|
|
6768
6869
|
|
|
6769
|
-
status = pjmedia_conf_add_port(
|
|
6870
|
+
status = pjmedia_conf_add_port(ae->conf, call->inv->pool, ae->flite_cbp.port, NULL, &ae->flite_cbp.slot);
|
|
6770
6871
|
if (status != PJ_SUCCESS) {
|
|
6771
6872
|
set_error("pjmedia_conf_add_port failed");
|
|
6772
6873
|
return false;
|
|
6773
6874
|
}
|
|
6774
6875
|
|
|
6775
|
-
|
|
6876
|
+
return connect_feature_port_to_stream_port(call, ae, &ae->flite_cbp, CONNECTION_MODE_SOURCE);
|
|
6877
|
+
}
|
|
6878
|
+
|
|
6879
|
+
bool prepare_pocketsphinx(Call *call, AudioEndpoint *ae) {
|
|
6880
|
+
printf("prepare_pocketsphinx call.id=%i\n", call->id);
|
|
6881
|
+
pj_status_t status;
|
|
6882
|
+
|
|
6883
|
+
if(ae->pocketsphinx_cbp.port) {
|
|
6884
|
+
printf("already prepared\n");
|
|
6885
|
+
return true;
|
|
6886
|
+
}
|
|
6887
|
+
|
|
6888
|
+
status = pjmedia_pocketsphinx_port_create(
|
|
6889
|
+
call->inv->pool, PJMEDIA_PIA_SRATE(&ae->stream_cbp.port->info),
|
|
6890
|
+
PJMEDIA_PIA_CCNT(&ae->stream_cbp.port->info),
|
|
6891
|
+
PJMEDIA_PIA_SPF(&ae->stream_cbp.port->info),
|
|
6892
|
+
PJMEDIA_PIA_BITS(&ae->stream_cbp.port->info),
|
|
6893
|
+
on_speech_transcript,
|
|
6894
|
+
call,
|
|
6895
|
+
&ae->pocketsphinx_cbp.port);
|
|
6776
6896
|
if (status != PJ_SUCCESS) {
|
|
6777
|
-
set_error("
|
|
6897
|
+
set_error("pjmedia_pocketsphinx_port_create failed");
|
|
6778
6898
|
return false;
|
|
6779
6899
|
}
|
|
6780
6900
|
|
|
6781
|
-
|
|
6782
|
-
|
|
6901
|
+
status = pjmedia_conf_add_port(ae->conf, call->inv->pool, ae->pocketsphinx_cbp.port, NULL, &ae->pocketsphinx_cbp.slot);
|
|
6902
|
+
if (status != PJ_SUCCESS) {
|
|
6903
|
+
set_error("pjmedia_conf_add_port failed");
|
|
6904
|
+
return false;
|
|
6905
|
+
}
|
|
6783
6906
|
|
|
6907
|
+
return connect_feature_port_to_stream_port(call, ae, &ae->pocketsphinx_cbp, CONNECTION_MODE_SINK);
|
|
6908
|
+
}
|
|
6784
6909
|
|
|
6785
6910
|
void on_rx_notify(pjsip_evsub *sub, pjsip_rx_data *rdata, int *p_st_code,
|
|
6786
6911
|
pj_str_t **p_st_text, pjsip_hdr *res_hdr,
|
|
@@ -8168,8 +8293,8 @@ static int g_now;
|
|
|
8168
8293
|
|
|
8169
8294
|
void check_digit_buffer(Call *call, int mode) {
|
|
8170
8295
|
// addon_log(L_DBG, "check_digit_buffer g_now=%i for call_id=%i and mode=%i
|
|
8171
|
-
// timestamp=%i len=%i\n", g_now,
|
|
8172
|
-
//
|
|
8296
|
+
// timestamp=%i len=%i\n", g_now, call->id, mode, call->last_digit_timestamp[mode],
|
|
8297
|
+
// call->DigitBufferLength[mode]);
|
|
8173
8298
|
char evt[1024];
|
|
8174
8299
|
|
|
8175
8300
|
for (int i = 0; i < call->media_count; i++) {
|
|
@@ -8193,10 +8318,10 @@ void check_digit_buffer(Call *call, int mode) {
|
|
|
8193
8318
|
}
|
|
8194
8319
|
|
|
8195
8320
|
void check_digit_buffers(long id, long val) {
|
|
8196
|
-
Call *
|
|
8321
|
+
Call *call = (Call *)val;
|
|
8197
8322
|
|
|
8198
|
-
check_digit_buffer(
|
|
8199
|
-
check_digit_buffer(
|
|
8323
|
+
check_digit_buffer(call, DTMF_MODE_RFC2833);
|
|
8324
|
+
check_digit_buffer(call, DTMF_MODE_INBAND);
|
|
8200
8325
|
}
|
|
8201
8326
|
|
|
8202
8327
|
static int digit_buffer_thread(void *arg) {
|