sip-lab 1.24.0 → 1.27.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/package.json +3 -2
- package/prebuilds/linux-x64/sip-lab.node +0 -0
- package/runtests +80 -0
- package/src/sip.cpp +143 -97
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sip-lab",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.27.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"engines": {
|
|
@@ -45,6 +45,7 @@
|
|
|
45
45
|
"DEV.md",
|
|
46
46
|
"samples",
|
|
47
47
|
"prebuilds",
|
|
48
|
-
"pocketsphinx"
|
|
48
|
+
"pocketsphinx",
|
|
49
|
+
"runtests"
|
|
49
50
|
]
|
|
50
51
|
}
|
|
Binary file
|
package/runtests
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
set -o nounset
|
|
4
|
+
|
|
5
|
+
function usage() {
|
|
6
|
+
cat <<EOF
|
|
7
|
+
Usage: $0 [-g]
|
|
8
|
+
|
|
9
|
+
Details:
|
|
10
|
+
-g : run each test inside gdb
|
|
11
|
+
EOF
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
use_gdb=0
|
|
15
|
+
|
|
16
|
+
while getopts "gh" o; do
|
|
17
|
+
case "${o}" in
|
|
18
|
+
g)
|
|
19
|
+
use_gdb=1
|
|
20
|
+
;;
|
|
21
|
+
h)
|
|
22
|
+
usage
|
|
23
|
+
exit 0
|
|
24
|
+
;;
|
|
25
|
+
*)
|
|
26
|
+
usage
|
|
27
|
+
exit 1
|
|
28
|
+
;;
|
|
29
|
+
esac
|
|
30
|
+
done
|
|
31
|
+
shift $((OPTIND-1))
|
|
32
|
+
|
|
33
|
+
successful_tests=()
|
|
34
|
+
|
|
35
|
+
function output_successful_tests() {
|
|
36
|
+
echo "Successful tests:"
|
|
37
|
+
for t in "${successful_tests[@]}"
|
|
38
|
+
do
|
|
39
|
+
echo " - $t"
|
|
40
|
+
done
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
echo
|
|
44
|
+
|
|
45
|
+
for i in $(ls samples/*.js)
|
|
46
|
+
do
|
|
47
|
+
start_time=$(date +%s.%N)
|
|
48
|
+
|
|
49
|
+
if [[ $use_gdb -eq 0 ]]
|
|
50
|
+
then
|
|
51
|
+
node $i
|
|
52
|
+
else
|
|
53
|
+
gdb -ex "handle SIGSEGV stop" -ex "run" -ex "bt" -ex "quit" --args node $i
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
if [[ $? -ne 0 ]]
|
|
57
|
+
then
|
|
58
|
+
echo "$i failed"
|
|
59
|
+
echo
|
|
60
|
+
output_successful_tests
|
|
61
|
+
exit 1
|
|
62
|
+
else
|
|
63
|
+
end_time=$(date +%s.%N)
|
|
64
|
+
duration=$(echo "$end_time - $start_time" | bc)
|
|
65
|
+
formatted_duration=$(printf "%.2f seconds" $duration)
|
|
66
|
+
successful_tests+=("$i: duration=$formatted_duration")
|
|
67
|
+
|
|
68
|
+
echo
|
|
69
|
+
echo "$i failed"
|
|
70
|
+
fi
|
|
71
|
+
done
|
|
72
|
+
|
|
73
|
+
echo
|
|
74
|
+
|
|
75
|
+
echo "Success. All tests passed"
|
|
76
|
+
echo
|
|
77
|
+
output_successful_tests
|
|
78
|
+
echo
|
|
79
|
+
echo "Everything OK"
|
|
80
|
+
echo
|
package/src/sip.cpp
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#include <arpa/inet.h>
|
|
2
|
+
#include <netdb.h>
|
|
2
3
|
|
|
3
4
|
#include "sip.hpp"
|
|
4
5
|
|
|
@@ -305,8 +306,18 @@ struct Subscription {
|
|
|
305
306
|
struct ConfBridgePort {
|
|
306
307
|
unsigned slot;
|
|
307
308
|
pjmedia_port *port;
|
|
309
|
+
short connection_mode;
|
|
308
310
|
};
|
|
309
311
|
|
|
312
|
+
#define FP_DTMFDET 0
|
|
313
|
+
#define FP_WAV_PLAYER 1
|
|
314
|
+
#define FP_WAV_WRITER 2
|
|
315
|
+
#define FP_TONEGEN 3
|
|
316
|
+
#define FP_FAX 4
|
|
317
|
+
#define FP_SPEECH_SYNTH 5
|
|
318
|
+
#define FP_SPEECH_RECOG 6
|
|
319
|
+
#define MAX_FP 7
|
|
320
|
+
|
|
310
321
|
struct AudioEndpoint {
|
|
311
322
|
pjmedia_transport *med_transport;
|
|
312
323
|
pjmedia_stream *med_stream;
|
|
@@ -322,13 +333,7 @@ struct AudioEndpoint {
|
|
|
322
333
|
pjmedia_port *null_port;
|
|
323
334
|
|
|
324
335
|
ConfBridgePort stream_cbp;
|
|
325
|
-
ConfBridgePort
|
|
326
|
-
ConfBridgePort wav_writer_cbp;
|
|
327
|
-
ConfBridgePort tonegen_cbp;
|
|
328
|
-
ConfBridgePort dtmfdet_cbp;
|
|
329
|
-
ConfBridgePort fax_cbp;
|
|
330
|
-
ConfBridgePort flite_cbp;
|
|
331
|
-
ConfBridgePort pocketsphinx_cbp;
|
|
336
|
+
ConfBridgePort feature_cbps[MAX_FP];
|
|
332
337
|
};
|
|
333
338
|
|
|
334
339
|
struct VideoEndpoint {
|
|
@@ -779,7 +784,7 @@ static int find_endpoint_by_inband_dtmf_media_port(Call *call,
|
|
|
779
784
|
MediaEndpoint *me = (MediaEndpoint *)call->media[i];
|
|
780
785
|
if (ENDPOINT_TYPE_AUDIO == me->type) {
|
|
781
786
|
AudioEndpoint *ae = (AudioEndpoint *)me->endpoint.audio;
|
|
782
|
-
if (ae->
|
|
787
|
+
if (ae->feature_cbps[FP_DTMFDET].port && (pjmedia_port *)ae->feature_cbps[FP_DTMFDET].port == port) {
|
|
783
788
|
return i;
|
|
784
789
|
}
|
|
785
790
|
}
|
|
@@ -2796,9 +2801,47 @@ bool dlg_set_transport_by_t(Transport *t, pjsip_dialog *dlg) {
|
|
|
2796
2801
|
return true;
|
|
2797
2802
|
}
|
|
2798
2803
|
|
|
2799
|
-
|
|
2804
|
+
bool is_ip_address(const char *hostname) {
|
|
2805
|
+
struct sockaddr_in sa;
|
|
2806
|
+
return inet_pton(AF_INET, hostname, &(sa.sin_addr)) != 0;
|
|
2807
|
+
}
|
|
2808
|
+
|
|
2809
|
+
void build_transport_tag(char *dest, const char *type, const char *hostname,
|
|
2800
2810
|
int port) {
|
|
2801
|
-
|
|
2811
|
+
struct addrinfo hints, * res, *p;
|
|
2812
|
+
|
|
2813
|
+
if(is_ip_address(hostname)) {
|
|
2814
|
+
sprintf(dest, "%s:%s:%d", type, hostname, port);
|
|
2815
|
+
return;
|
|
2816
|
+
}
|
|
2817
|
+
|
|
2818
|
+
memset(&hints, 0, sizeof(hints));
|
|
2819
|
+
hints.ai_family = AF_UNSPEC; // AF_INET or AF_INET6 to force version
|
|
2820
|
+
hints.ai_socktype = SOCK_STREAM;
|
|
2821
|
+
|
|
2822
|
+
// Resolve the domain name
|
|
2823
|
+
int status = getaddrinfo(hostname, NULL, &hints, &res);
|
|
2824
|
+
if (status != 0) {
|
|
2825
|
+
printf("build_transport_tag getaddrinfo: %s\n", gai_strerror(status));
|
|
2826
|
+
sprintf(dest, "%s:%s:%d", type, hostname, port);
|
|
2827
|
+
} else {
|
|
2828
|
+
for (p = res; p != NULL; p = p->ai_next) {
|
|
2829
|
+
void *addr;
|
|
2830
|
+
if (p->ai_family == AF_INET) { // IPv4
|
|
2831
|
+
struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
|
|
2832
|
+
addr = &(ipv4->sin_addr);
|
|
2833
|
+
} else { // IPv6
|
|
2834
|
+
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
|
|
2835
|
+
addr = &(ipv6->sin6_addr);
|
|
2836
|
+
}
|
|
2837
|
+
char ipstr[INET6_ADDRSTRLEN];
|
|
2838
|
+
inet_ntop(p->ai_family, addr, ipstr, sizeof(ipstr));
|
|
2839
|
+
sprintf(dest, "%s:%s:%d", type, ipstr, port);
|
|
2840
|
+
break;
|
|
2841
|
+
}
|
|
2842
|
+
}
|
|
2843
|
+
|
|
2844
|
+
freeaddrinfo(res);
|
|
2802
2845
|
}
|
|
2803
2846
|
|
|
2804
2847
|
void build_transport_tag_from_pjsip_transport(char *dest, pjsip_transport *t) {
|
|
@@ -2810,6 +2853,7 @@ void build_transport_tag_from_pjsip_transport(char *dest, pjsip_transport *t) {
|
|
|
2810
2853
|
assert(t->local_name.host.slen < 16);
|
|
2811
2854
|
strncpy(address, t->local_name.host.ptr, t->local_name.host.slen);
|
|
2812
2855
|
address[t->local_name.host.slen] = 0;
|
|
2856
|
+
printf("build_transport_tag_from_pjsip_transport address=%s\n", address);
|
|
2813
2857
|
|
|
2814
2858
|
if (t->key.type == PJSIP_TRANSPORT_UDP) {
|
|
2815
2859
|
type = "udp";
|
|
@@ -3082,7 +3126,7 @@ pj_status_t audio_endpoint_send_dtmf(Call *call, AudioEndpoint *ae,
|
|
|
3082
3126
|
tone.on_msec = ON_DURATION;
|
|
3083
3127
|
tone.off_msec = OFF_DURATION;
|
|
3084
3128
|
tone.volume = 0;
|
|
3085
|
-
status = pjmedia_tonegen_play_digits((pjmedia_port *)ae->
|
|
3129
|
+
status = pjmedia_tonegen_play_digits((pjmedia_port *)ae->feature_cbps[FP_TONEGEN].port, 1,
|
|
3086
3130
|
&tone, 0);
|
|
3087
3131
|
if (status != PJ_SUCCESS) {
|
|
3088
3132
|
set_error("pjmedia_tonegen_play_digits failed.");
|
|
@@ -3789,7 +3833,7 @@ pj_status_t audio_endpoint_start_speech_synth(Call *call, AudioEndpoint *ae, con
|
|
|
3789
3833
|
return -1;
|
|
3790
3834
|
}
|
|
3791
3835
|
|
|
3792
|
-
pjmedia_flite_port_speak(ae->
|
|
3836
|
+
pjmedia_flite_port_speak(ae->feature_cbps[FP_SPEECH_SYNTH].port, text, flags);
|
|
3793
3837
|
|
|
3794
3838
|
return PJ_SUCCESS;
|
|
3795
3839
|
}
|
|
@@ -4122,36 +4166,27 @@ out:
|
|
|
4122
4166
|
return 0;
|
|
4123
4167
|
}
|
|
4124
4168
|
|
|
4125
|
-
pj_status_t audio_endpoint_stop_speech_synth(Call *call, AudioEndpoint *ae) {
|
|
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);
|
|
4131
|
-
}
|
|
4132
|
-
|
|
4133
4169
|
pj_status_t audio_endpoint_stop_play_wav(Call *call, AudioEndpoint *ae) {
|
|
4134
|
-
return audio_endpoint_remove_port(call, ae, &ae->
|
|
4170
|
+
return audio_endpoint_remove_port(call, ae, &ae->feature_cbps[FP_WAV_PLAYER]);
|
|
4135
4171
|
}
|
|
4136
4172
|
|
|
4137
4173
|
pj_status_t audio_endpoint_stop_record_wav(Call *call, AudioEndpoint *ae) {
|
|
4138
|
-
return audio_endpoint_remove_port(call, ae, &ae->
|
|
4174
|
+
return audio_endpoint_remove_port(call, ae, &ae->feature_cbps[FP_WAV_WRITER]);
|
|
4139
4175
|
}
|
|
4140
4176
|
|
|
4141
4177
|
pj_status_t audio_endpoint_stop_fax(Call *call, AudioEndpoint *ae) {
|
|
4142
|
-
return audio_endpoint_remove_port(call, ae, &ae->
|
|
4178
|
+
return audio_endpoint_remove_port(call, ae, &ae->feature_cbps[FP_FAX]);
|
|
4143
4179
|
}
|
|
4144
4180
|
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
int pjw_call_stop_speech_synth(long call_id, const char *json) {
|
|
4148
|
-
return audio_endpoint_stop_op(call_id, json, audio_endpoint_stop_speech_synth);
|
|
4181
|
+
pj_status_t audio_endpoint_stop_speech_synth(Call *call, AudioEndpoint *ae) {
|
|
4182
|
+
return audio_endpoint_remove_port(call, ae, &ae->feature_cbps[FP_SPEECH_SYNTH]);
|
|
4149
4183
|
}
|
|
4150
4184
|
|
|
4151
|
-
|
|
4152
|
-
return
|
|
4185
|
+
pj_status_t audio_endpoint_stop_speech_recog(Call *call, AudioEndpoint *ae) {
|
|
4186
|
+
return audio_endpoint_remove_port(call, ae, &ae->feature_cbps[FP_SPEECH_RECOG]);
|
|
4153
4187
|
}
|
|
4154
4188
|
|
|
4189
|
+
|
|
4155
4190
|
int pjw_call_stop_play_wav(long call_id, const char *json) {
|
|
4156
4191
|
return audio_endpoint_stop_op(call_id, json, audio_endpoint_stop_play_wav);
|
|
4157
4192
|
}
|
|
@@ -4164,6 +4199,14 @@ int pjw_call_stop_fax(long call_id, const char *json) {
|
|
|
4164
4199
|
return audio_endpoint_stop_op(call_id, json, audio_endpoint_stop_fax);
|
|
4165
4200
|
}
|
|
4166
4201
|
|
|
4202
|
+
int pjw_call_stop_speech_synth(long call_id, const char *json) {
|
|
4203
|
+
return audio_endpoint_stop_op(call_id, json, audio_endpoint_stop_speech_synth);
|
|
4204
|
+
}
|
|
4205
|
+
|
|
4206
|
+
int pjw_call_stop_speech_recog(long call_id, const char *json) {
|
|
4207
|
+
return audio_endpoint_stop_op(call_id, json, audio_endpoint_stop_speech_recog);
|
|
4208
|
+
}
|
|
4209
|
+
|
|
4167
4210
|
|
|
4168
4211
|
int pjw_call_start_fax(long call_id, const char *json) {
|
|
4169
4212
|
PJW_LOCK();
|
|
@@ -4640,13 +4683,10 @@ void close_audio_endpoint_ports_and_conf(Call *call, AudioEndpoint *ae) {
|
|
|
4640
4683
|
pj_status_t status;
|
|
4641
4684
|
|
|
4642
4685
|
audio_endpoint_remove_port(call, ae, &ae->stream_cbp);
|
|
4643
|
-
|
|
4644
|
-
|
|
4645
|
-
|
|
4646
|
-
|
|
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);
|
|
4686
|
+
|
|
4687
|
+
for(int i=0 ; i<MAX_FP ; i++) {
|
|
4688
|
+
audio_endpoint_remove_port(call, ae, &ae->feature_cbps[i]);
|
|
4689
|
+
}
|
|
4650
4690
|
|
|
4651
4691
|
if (ae->master_port) {
|
|
4652
4692
|
status = pjmedia_master_port_stop(ae->master_port);
|
|
@@ -4677,17 +4717,17 @@ void close_audio_endpoint_ports_and_conf(Call *call, AudioEndpoint *ae) {
|
|
|
4677
4717
|
}
|
|
4678
4718
|
}
|
|
4679
4719
|
|
|
4680
|
-
bool connect_feature_port_to_stream_port(Call *call, AudioEndpoint *ae, ConfBridgePort *cbp
|
|
4720
|
+
bool connect_feature_port_to_stream_port(Call *call, AudioEndpoint *ae, ConfBridgePort *cbp) {
|
|
4681
4721
|
pj_status_t status;
|
|
4682
4722
|
|
|
4683
|
-
if(connection_mode == CONNECTION_MODE_SOURCE || connection_mode == CONNECTION_MODE_SOURCE_AND_SINK) {
|
|
4723
|
+
if(cbp->connection_mode == CONNECTION_MODE_SOURCE || cbp->connection_mode == CONNECTION_MODE_SOURCE_AND_SINK) {
|
|
4684
4724
|
status = pjmedia_conf_connect_port(ae->conf, cbp->slot, ae->stream_cbp.slot, 0);
|
|
4685
4725
|
if (status != PJ_SUCCESS) {
|
|
4686
4726
|
set_error("pjmedia_conf_connect_port failed");
|
|
4687
4727
|
return false;
|
|
4688
4728
|
}
|
|
4689
4729
|
}
|
|
4690
|
-
if(connection_mode == CONNECTION_MODE_SINK || connection_mode == CONNECTION_MODE_SOURCE_AND_SINK) {
|
|
4730
|
+
if(cbp->connection_mode == CONNECTION_MODE_SINK || cbp->connection_mode == CONNECTION_MODE_SOURCE_AND_SINK) {
|
|
4691
4731
|
status = pjmedia_conf_connect_port(ae->conf, ae->stream_cbp.slot, cbp->slot, 0);
|
|
4692
4732
|
printf("status=%i\n" ,status);
|
|
4693
4733
|
if (status != PJ_SUCCESS) {
|
|
@@ -4860,32 +4900,10 @@ bool restart_media_stream(Call *call, MediaEndpoint *me,
|
|
|
4860
4900
|
}
|
|
4861
4901
|
|
|
4862
4902
|
// Need to connect ports to new stream port
|
|
4863
|
-
|
|
4864
|
-
|
|
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;
|
|
4903
|
+
for(int i=0 ; i<MAX_FP ; i++) {
|
|
4904
|
+
if(ae->feature_cbps[i].port) {
|
|
4905
|
+
if(!connect_feature_port_to_stream_port(call, ae, &ae->feature_cbps[i])) return false;
|
|
4906
|
+
}
|
|
4889
4907
|
}
|
|
4890
4908
|
}
|
|
4891
4909
|
|
|
@@ -5379,7 +5397,7 @@ static pj_bool_t on_rx_request(pjsip_rx_data *rdata) {
|
|
|
5379
5397
|
|
|
5380
5398
|
long transport_id;
|
|
5381
5399
|
|
|
5382
|
-
//
|
|
5400
|
+
//printf("on_rx_request transport_tag=%s\n", tag);
|
|
5383
5401
|
|
|
5384
5402
|
TransportMap::iterator iter = g_TransportMap.find(tag);
|
|
5385
5403
|
if (iter != g_TransportMap.end()) {
|
|
@@ -5490,7 +5508,7 @@ static pj_bool_t on_rx_request(pjsip_rx_data *rdata) {
|
|
|
5490
5508
|
|
|
5491
5509
|
long transport_id;
|
|
5492
5510
|
|
|
5493
|
-
|
|
5511
|
+
printf("on_rx_request INVITE transport_tag=%s\n", tag);
|
|
5494
5512
|
|
|
5495
5513
|
TransportMap::iterator iter = g_TransportMap.find(tag);
|
|
5496
5514
|
if (iter != g_TransportMap.end()) {
|
|
@@ -6707,7 +6725,9 @@ bool prepare_tonegen(Call *call, AudioEndpoint *ae) {
|
|
|
6707
6725
|
printf("prepare_tone_gen call.id=%i\n", call->id);
|
|
6708
6726
|
pj_status_t status;
|
|
6709
6727
|
|
|
6710
|
-
|
|
6728
|
+
ConfBridgePort *fp = &ae->feature_cbps[FP_TONEGEN];
|
|
6729
|
+
|
|
6730
|
+
if(fp->port) {
|
|
6711
6731
|
printf("already prepared\n");
|
|
6712
6732
|
return true;
|
|
6713
6733
|
}
|
|
@@ -6716,24 +6736,28 @@ bool prepare_tonegen(Call *call, AudioEndpoint *ae) {
|
|
|
6716
6736
|
call->inv->pool, PJMEDIA_PIA_SRATE(&ae->stream_cbp.port->info),
|
|
6717
6737
|
PJMEDIA_PIA_CCNT(&ae->stream_cbp.port->info),
|
|
6718
6738
|
PJMEDIA_PIA_SPF(&ae->stream_cbp.port->info),
|
|
6719
|
-
PJMEDIA_PIA_BITS(&ae->stream_cbp.port->info), 0, &
|
|
6739
|
+
PJMEDIA_PIA_BITS(&ae->stream_cbp.port->info), 0, &fp->port);
|
|
6720
6740
|
if (status != PJ_SUCCESS) {
|
|
6721
6741
|
set_error("pjmedia_tonegen_create failed");
|
|
6722
6742
|
return false;
|
|
6723
6743
|
}
|
|
6724
6744
|
|
|
6725
|
-
status = pjmedia_conf_add_port(ae->conf, call->inv->pool,
|
|
6745
|
+
status = pjmedia_conf_add_port(ae->conf, call->inv->pool, fp->port, NULL, &fp->slot);
|
|
6726
6746
|
if (status != PJ_SUCCESS) {
|
|
6727
6747
|
set_error("pjmedia_conf_add_port failed");
|
|
6728
6748
|
return false;
|
|
6729
6749
|
}
|
|
6730
6750
|
|
|
6731
|
-
|
|
6751
|
+
fp->connection_mode = CONNECTION_MODE_SOURCE;
|
|
6752
|
+
|
|
6753
|
+
return connect_feature_port_to_stream_port(call, ae, fp);
|
|
6732
6754
|
}
|
|
6733
6755
|
|
|
6734
6756
|
bool prepare_wav_player(Call *call, AudioEndpoint *ae, const char *file, unsigned flags, bool end_of_file_event) {
|
|
6735
6757
|
pj_status_t status;
|
|
6736
6758
|
|
|
6759
|
+
ConfBridgePort *fp = &ae->feature_cbps[FP_WAV_PLAYER];
|
|
6760
|
+
|
|
6737
6761
|
unsigned wav_ptime;
|
|
6738
6762
|
wav_ptime = PJMEDIA_PIA_SPF(&ae->stream_cbp.port->info) * 1000 /
|
|
6739
6763
|
PJMEDIA_PIA_SRATE(&ae->stream_cbp.port->info);
|
|
@@ -6744,7 +6768,7 @@ bool prepare_wav_player(Call *call, AudioEndpoint *ae, const char *file, unsigne
|
|
|
6744
6768
|
wav_ptime,
|
|
6745
6769
|
flags,
|
|
6746
6770
|
-1, /* buf size */
|
|
6747
|
-
&
|
|
6771
|
+
&fp->port
|
|
6748
6772
|
);
|
|
6749
6773
|
|
|
6750
6774
|
if (status != PJ_SUCCESS) {
|
|
@@ -6753,71 +6777,83 @@ bool prepare_wav_player(Call *call, AudioEndpoint *ae, const char *file, unsigne
|
|
|
6753
6777
|
}
|
|
6754
6778
|
|
|
6755
6779
|
if (end_of_file_event) {
|
|
6756
|
-
status = pjmedia_wav_player_set_eof_cb2(
|
|
6780
|
+
status = pjmedia_wav_player_set_eof_cb2(fp->port, (void*)call, on_end_of_file);
|
|
6757
6781
|
if (status != PJ_SUCCESS) {
|
|
6758
6782
|
set_error("pjmedia_wav_player_set_eof_cb2 failed");
|
|
6759
6783
|
return false;
|
|
6760
6784
|
}
|
|
6761
6785
|
}
|
|
6762
6786
|
|
|
6763
|
-
status = pjmedia_conf_add_port(ae->conf, call->inv->pool,
|
|
6787
|
+
status = pjmedia_conf_add_port(ae->conf, call->inv->pool, fp->port, NULL, &fp->slot);
|
|
6764
6788
|
if (status != PJ_SUCCESS) {
|
|
6765
6789
|
set_error("pjmedia_conf_add_port failed");
|
|
6766
6790
|
return false;
|
|
6767
6791
|
}
|
|
6768
6792
|
|
|
6769
|
-
|
|
6793
|
+
fp->connection_mode = CONNECTION_MODE_SOURCE;
|
|
6794
|
+
|
|
6795
|
+
return connect_feature_port_to_stream_port(call, ae, fp);
|
|
6770
6796
|
}
|
|
6771
6797
|
|
|
6772
6798
|
bool prepare_wav_writer(Call *call, AudioEndpoint *ae, const char *file) {
|
|
6773
6799
|
pj_status_t status;
|
|
6774
6800
|
|
|
6801
|
+
ConfBridgePort *fp = &ae->feature_cbps[FP_WAV_WRITER];
|
|
6802
|
+
|
|
6775
6803
|
status = pjmedia_wav_writer_port_create(
|
|
6776
6804
|
call->inv->pool, file, PJMEDIA_PIA_SRATE(&ae->stream_cbp.port->info),
|
|
6777
6805
|
PJMEDIA_PIA_CCNT(&ae->stream_cbp.port->info), PJMEDIA_PIA_SPF(&ae->stream_cbp.port->info),
|
|
6778
6806
|
PJMEDIA_PIA_BITS(&ae->stream_cbp.port->info), PJMEDIA_FILE_WRITE_PCM, 0,
|
|
6779
|
-
(pjmedia_port **)&
|
|
6807
|
+
(pjmedia_port **)&fp->port);
|
|
6780
6808
|
if (status != PJ_SUCCESS) {
|
|
6781
6809
|
set_error("pjmedia_wav_write_port_create failed");
|
|
6782
6810
|
return false;
|
|
6783
6811
|
}
|
|
6784
6812
|
|
|
6785
|
-
status = pjmedia_conf_add_port(ae->conf, call->inv->pool,
|
|
6813
|
+
status = pjmedia_conf_add_port(ae->conf, call->inv->pool, fp->port, NULL, &fp->slot);
|
|
6786
6814
|
if (status != PJ_SUCCESS) {
|
|
6787
6815
|
set_error("pjmedia_conf_add_port failed");
|
|
6788
6816
|
return false;
|
|
6789
6817
|
}
|
|
6790
6818
|
|
|
6791
|
-
|
|
6819
|
+
fp->connection_mode = CONNECTION_MODE_SINK;
|
|
6820
|
+
|
|
6821
|
+
return connect_feature_port_to_stream_port(call, ae, fp);
|
|
6792
6822
|
}
|
|
6793
6823
|
|
|
6794
6824
|
bool prepare_dtmfdet(Call *call, AudioEndpoint *ae) {
|
|
6795
6825
|
pj_status_t status;
|
|
6826
|
+
|
|
6827
|
+
ConfBridgePort *fp = &ae->feature_cbps[FP_DTMFDET];
|
|
6828
|
+
|
|
6796
6829
|
status = pjmedia_dtmfdet_create(
|
|
6797
6830
|
call->inv->pool,
|
|
6798
6831
|
PJMEDIA_PIA_SRATE(&ae->stream_cbp.port->info),
|
|
6799
6832
|
PJMEDIA_PIA_CCNT(&ae->stream_cbp.port->info),
|
|
6800
6833
|
PJMEDIA_PIA_SPF(&ae->stream_cbp.port->info),
|
|
6801
6834
|
PJMEDIA_PIA_BITS(&ae->stream_cbp.port->info),
|
|
6802
|
-
on_inband_dtmf, call, &
|
|
6835
|
+
on_inband_dtmf, call, &fp->port);
|
|
6803
6836
|
if (status != PJ_SUCCESS) {
|
|
6804
6837
|
set_error("pjmedia_dtmfdet_create failed");
|
|
6805
6838
|
return false;
|
|
6806
6839
|
}
|
|
6807
6840
|
|
|
6808
|
-
status = pjmedia_conf_add_port(ae->conf, call->inv->pool,
|
|
6841
|
+
status = pjmedia_conf_add_port(ae->conf, call->inv->pool, fp->port, NULL, &fp->slot);
|
|
6809
6842
|
if (status != PJ_SUCCESS) {
|
|
6810
6843
|
set_error("pjmedia_conf_add_port failed");
|
|
6811
6844
|
return false;
|
|
6812
6845
|
}
|
|
6813
6846
|
|
|
6814
|
-
|
|
6847
|
+
fp->connection_mode = CONNECTION_MODE_SINK;
|
|
6848
|
+
|
|
6849
|
+
return connect_feature_port_to_stream_port(call, ae, fp);
|
|
6815
6850
|
}
|
|
6816
6851
|
|
|
6817
|
-
bool prepare_fax(Call *call, AudioEndpoint *ae, bool is_sender, const char *file,
|
|
6818
|
-
unsigned flags) {
|
|
6852
|
+
bool prepare_fax(Call *call, AudioEndpoint *ae, bool is_sender, const char *file, unsigned flags) {
|
|
6819
6853
|
pj_status_t status;
|
|
6820
6854
|
|
|
6855
|
+
ConfBridgePort *fp = &ae->feature_cbps[FP_FAX];
|
|
6856
|
+
|
|
6821
6857
|
status = pjmedia_fax_port_create(
|
|
6822
6858
|
call->inv->pool,
|
|
6823
6859
|
PJMEDIA_PIA_SRATE(&ae->stream_cbp.port->info),
|
|
@@ -6825,26 +6861,29 @@ bool prepare_fax(Call *call, AudioEndpoint *ae, bool is_sender, const char *file
|
|
|
6825
6861
|
PJMEDIA_PIA_SPF(&ae->stream_cbp.port->info),
|
|
6826
6862
|
PJMEDIA_PIA_BITS(&ae->stream_cbp.port->info),
|
|
6827
6863
|
on_fax_result, call, is_sender, file,
|
|
6828
|
-
flags, &
|
|
6864
|
+
flags, &fp->port);
|
|
6829
6865
|
if (status != PJ_SUCCESS) {
|
|
6830
6866
|
set_error("pjmedia_fax_port_create failed");
|
|
6831
6867
|
return false;
|
|
6832
6868
|
}
|
|
6833
6869
|
|
|
6834
|
-
status = pjmedia_conf_add_port(ae->conf, call->inv->pool,
|
|
6870
|
+
status = pjmedia_conf_add_port(ae->conf, call->inv->pool, fp->port, NULL, &fp->slot);
|
|
6835
6871
|
if (status != PJ_SUCCESS) {
|
|
6836
6872
|
set_error("pjmedia_conf_add_port failed");
|
|
6837
6873
|
return false;
|
|
6838
6874
|
}
|
|
6839
6875
|
|
|
6840
|
-
|
|
6876
|
+
fp->connection_mode = CONNECTION_MODE_SOURCE_AND_SINK;
|
|
6877
|
+
|
|
6878
|
+
return connect_feature_port_to_stream_port(call, ae, fp);
|
|
6841
6879
|
}
|
|
6842
6880
|
|
|
6843
6881
|
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);
|
|
6845
6882
|
pj_status_t status;
|
|
6846
6883
|
|
|
6847
|
-
|
|
6884
|
+
ConfBridgePort *fp = &ae->feature_cbps[FP_SPEECH_SYNTH];
|
|
6885
|
+
|
|
6886
|
+
if(fp->port) {
|
|
6848
6887
|
printf("already prepared\n");
|
|
6849
6888
|
return true;
|
|
6850
6889
|
}
|
|
@@ -6853,34 +6892,39 @@ bool prepare_flite(Call *call, AudioEndpoint *ae, const char *voice, bool end_of
|
|
|
6853
6892
|
call->inv->pool, PJMEDIA_PIA_SRATE(&ae->stream_cbp.port->info),
|
|
6854
6893
|
PJMEDIA_PIA_CCNT(&ae->stream_cbp.port->info),
|
|
6855
6894
|
PJMEDIA_PIA_SPF(&ae->stream_cbp.port->info),
|
|
6856
|
-
PJMEDIA_PIA_BITS(&ae->stream_cbp.port->info),
|
|
6895
|
+
PJMEDIA_PIA_BITS(&ae->stream_cbp.port->info),
|
|
6896
|
+
voice,
|
|
6897
|
+
&fp->port);
|
|
6857
6898
|
if (status != PJ_SUCCESS) {
|
|
6858
6899
|
set_error("pjmedia_flite_port_create failed");
|
|
6859
6900
|
return false;
|
|
6860
6901
|
}
|
|
6861
6902
|
|
|
6862
6903
|
if (end_of_speech_event) {
|
|
6863
|
-
status = pjmedia_flite_port_set_eof_cb(
|
|
6904
|
+
status = pjmedia_flite_port_set_eof_cb(fp->port, (void*)call, on_end_of_speech);
|
|
6864
6905
|
if (status != PJ_SUCCESS) {
|
|
6865
6906
|
set_error("pjmedia_flite_port_set_eof_cb failed");
|
|
6866
6907
|
return false;
|
|
6867
6908
|
}
|
|
6868
6909
|
}
|
|
6869
6910
|
|
|
6870
|
-
status = pjmedia_conf_add_port(ae->conf, call->inv->pool,
|
|
6911
|
+
status = pjmedia_conf_add_port(ae->conf, call->inv->pool, fp->port, NULL, &fp->slot);
|
|
6871
6912
|
if (status != PJ_SUCCESS) {
|
|
6872
6913
|
set_error("pjmedia_conf_add_port failed");
|
|
6873
6914
|
return false;
|
|
6874
6915
|
}
|
|
6875
6916
|
|
|
6876
|
-
|
|
6917
|
+
fp->connection_mode = CONNECTION_MODE_SOURCE;
|
|
6918
|
+
|
|
6919
|
+
return connect_feature_port_to_stream_port(call, ae, fp);
|
|
6877
6920
|
}
|
|
6878
6921
|
|
|
6879
6922
|
bool prepare_pocketsphinx(Call *call, AudioEndpoint *ae) {
|
|
6880
|
-
printf("prepare_pocketsphinx call.id=%i\n", call->id);
|
|
6881
6923
|
pj_status_t status;
|
|
6882
6924
|
|
|
6883
|
-
|
|
6925
|
+
ConfBridgePort *fp = &ae->feature_cbps[FP_SPEECH_RECOG];
|
|
6926
|
+
|
|
6927
|
+
if(fp->port) {
|
|
6884
6928
|
printf("already prepared\n");
|
|
6885
6929
|
return true;
|
|
6886
6930
|
}
|
|
@@ -6892,19 +6936,21 @@ bool prepare_pocketsphinx(Call *call, AudioEndpoint *ae) {
|
|
|
6892
6936
|
PJMEDIA_PIA_BITS(&ae->stream_cbp.port->info),
|
|
6893
6937
|
on_speech_transcript,
|
|
6894
6938
|
call,
|
|
6895
|
-
&
|
|
6939
|
+
&fp->port);
|
|
6896
6940
|
if (status != PJ_SUCCESS) {
|
|
6897
6941
|
set_error("pjmedia_pocketsphinx_port_create failed");
|
|
6898
6942
|
return false;
|
|
6899
6943
|
}
|
|
6900
6944
|
|
|
6901
|
-
status = pjmedia_conf_add_port(ae->conf, call->inv->pool,
|
|
6945
|
+
status = pjmedia_conf_add_port(ae->conf, call->inv->pool, fp->port, NULL, &fp->slot);
|
|
6902
6946
|
if (status != PJ_SUCCESS) {
|
|
6903
6947
|
set_error("pjmedia_conf_add_port failed");
|
|
6904
6948
|
return false;
|
|
6905
6949
|
}
|
|
6906
6950
|
|
|
6907
|
-
|
|
6951
|
+
fp->connection_mode = CONNECTION_MODE_SINK;
|
|
6952
|
+
|
|
6953
|
+
return connect_feature_port_to_stream_port(call, ae, fp);
|
|
6908
6954
|
}
|
|
6909
6955
|
|
|
6910
6956
|
void on_rx_notify(pjsip_evsub *sub, pjsip_rx_data *rdata, int *p_st_code,
|