sip-lab 1.22.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 +5 -4
- package/binding.gyp +4 -0
- package/build_deps.sh +21 -1
- package/index.js +19 -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/start_play_wav_with_end_of_file_event.js +269 -0
- package/samples/start_play_wav_with_no_loop.js +257 -0
- package/samples/tcp_and_extra_headers.js +47 -1
- package/samples/text_to_speech.js +22 -3
- package/src/addon.cpp +72 -0
- package/src/event_templates.cpp +20 -7
- package/src/event_templates.hpp +6 -0
- package/src/pjmedia/include/pjmedia/flite_port.h +10 -4
- package/src/pjmedia/include/pjmedia/pocketsphinx_port.h +19 -0
- package/src/pjmedia/src/pjmedia/flite_port.c +91 -25
- package/src/pjmedia/src/pjmedia/pocketsphinx_port.c +273 -0
- package/src/sip.cpp +707 -507
- package/src/sip.hpp +5 -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,30 +616,31 @@ 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
|
|
|
641
639
|
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
|
-
pj_status_t
|
|
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++) {
|
|
@@ -851,7 +831,7 @@ static void on_inband_dtmf(pjmedia_port *port, void *user_data, char digit) {
|
|
|
851
831
|
ae->last_digit_timestamp[mode] = ms_timestamp();
|
|
852
832
|
PJW_UNLOCK();
|
|
853
833
|
} else {
|
|
854
|
-
char evt[
|
|
834
|
+
char evt[1024];
|
|
855
835
|
make_evt_dtmf(evt, sizeof(evt), call_id, 1, &d, mode, media_id);
|
|
856
836
|
dispatch_event(evt);
|
|
857
837
|
}
|
|
@@ -868,11 +848,60 @@ static void on_fax_result(pjmedia_port *port, void *user_data, int result) {
|
|
|
868
848
|
return;
|
|
869
849
|
}
|
|
870
850
|
|
|
871
|
-
char evt[
|
|
851
|
+
char evt[1024];
|
|
872
852
|
make_evt_fax_result(evt, sizeof(evt), call_id, result);
|
|
873
853
|
dispatch_event(evt);
|
|
874
854
|
}
|
|
875
855
|
|
|
856
|
+
static void on_end_of_file(pjmedia_port *port, void *user_data) {
|
|
857
|
+
if (g_shutting_down)
|
|
858
|
+
return;
|
|
859
|
+
|
|
860
|
+
long call_id;
|
|
861
|
+
if (!g_call_ids.get_id((long)user_data, call_id)) {
|
|
862
|
+
printf(
|
|
863
|
+
"on_end_of_file: Failed to get call_id. Event will not be notified.\n");
|
|
864
|
+
return;
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
char evt[1024];
|
|
868
|
+
make_evt_end_of_file(evt, sizeof(evt), call_id);
|
|
869
|
+
dispatch_event(evt);
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
static void on_end_of_speech(pjmedia_port *port, void *user_data) {
|
|
873
|
+
if (g_shutting_down)
|
|
874
|
+
return;
|
|
875
|
+
|
|
876
|
+
long call_id;
|
|
877
|
+
if (!g_call_ids.get_id((long)user_data, call_id)) {
|
|
878
|
+
printf(
|
|
879
|
+
"on_end_of_speech: Failed to get call_id. Event will not be notified.\n");
|
|
880
|
+
return;
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
char evt[1024];
|
|
884
|
+
make_evt_end_of_speech(evt, sizeof(evt), call_id);
|
|
885
|
+
dispatch_event(evt);
|
|
886
|
+
}
|
|
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
|
+
}
|
|
904
|
+
|
|
876
905
|
void dispatch_event(const char *evt) {
|
|
877
906
|
addon_log(L_DBG, "dispach_event called with evt=%s\n", evt);
|
|
878
907
|
// g_event_sink(evt);
|
|
@@ -3014,12 +3043,6 @@ int call_create(Transport *t, unsigned flags, pjsip_dialog *dlg,
|
|
|
3014
3043
|
}
|
|
3015
3044
|
// addon_log(L_DBG, "pjsip_dlg_add_usage OK\n");
|
|
3016
3045
|
|
|
3017
|
-
status = setup_call_conf(call);
|
|
3018
|
-
if (status != PJ_SUCCESS) {
|
|
3019
|
-
set_error("setup_call_conf failed");
|
|
3020
|
-
return -1;
|
|
3021
|
-
}
|
|
3022
|
-
|
|
3023
3046
|
return call_id;
|
|
3024
3047
|
}
|
|
3025
3048
|
|
|
@@ -3090,7 +3113,6 @@ pj_status_t send_dtmf(Call *call, const char *digits, int mode) {
|
|
|
3090
3113
|
return PJ_SUCCESS;
|
|
3091
3114
|
}
|
|
3092
3115
|
|
|
3093
|
-
// int pjw_call_send_dtmf(long call_id, const char *digits, int mode)
|
|
3094
3116
|
int pjw_call_send_dtmf(long call_id, const char *json) {
|
|
3095
3117
|
#define MAX_LENGTH \
|
|
3096
3118
|
31 // pjsip allows for 31 digits (inband allows for 32 digits)
|
|
@@ -3098,32 +3120,40 @@ int pjw_call_send_dtmf(long call_id, const char *json) {
|
|
|
3098
3120
|
PJW_LOCK();
|
|
3099
3121
|
clear_error();
|
|
3100
3122
|
|
|
3123
|
+
Call *call;
|
|
3124
|
+
|
|
3125
|
+
pj_status_t status;
|
|
3126
|
+
|
|
3101
3127
|
long val;
|
|
3128
|
+
|
|
3102
3129
|
char *digits;
|
|
3103
3130
|
int mode = 0;
|
|
3104
|
-
;
|
|
3105
3131
|
|
|
3106
|
-
|
|
3132
|
+
MediaEndpoint *me;
|
|
3133
|
+
AudioEndpoint *ae;
|
|
3134
|
+
int res;
|
|
3135
|
+
|
|
3136
|
+
int media_id = -1;
|
|
3107
3137
|
|
|
3108
3138
|
char buffer[MAX_JSON_INPUT];
|
|
3109
3139
|
|
|
3110
3140
|
Document document;
|
|
3111
3141
|
|
|
3112
|
-
const char *valid_params[] = {"digits", "mode", ""};
|
|
3142
|
+
const char *valid_params[] = {"digits", "mode", "media_id", ""};
|
|
3113
3143
|
|
|
3114
|
-
if (!
|
|
3144
|
+
if (!g_call_ids.get(call_id, val)) {
|
|
3145
|
+
set_error("Invalid call_id");
|
|
3115
3146
|
goto out;
|
|
3116
3147
|
}
|
|
3148
|
+
call = (Call *)val;
|
|
3117
3149
|
|
|
3118
|
-
if (!
|
|
3150
|
+
if (!parse_json(document, json, buffer, MAX_JSON_INPUT)) {
|
|
3119
3151
|
goto out;
|
|
3120
3152
|
}
|
|
3121
3153
|
|
|
3122
|
-
if (!
|
|
3123
|
-
set_error("Invalid call_id");
|
|
3154
|
+
if (!validate_params(document, valid_params)) {
|
|
3124
3155
|
goto out;
|
|
3125
3156
|
}
|
|
3126
|
-
call = (Call *)val;
|
|
3127
3157
|
|
|
3128
3158
|
if (json_get_string_param(document, "digits", false, &digits) <= 0) {
|
|
3129
3159
|
goto out;
|
|
@@ -3169,7 +3199,38 @@ int pjw_call_send_dtmf(long call_id, const char *json) {
|
|
|
3169
3199
|
adjusted_digits[len] = 0;
|
|
3170
3200
|
// addon_log(L_DBG, "adjusted_digits >>%s<<\n", adjusted_digits);
|
|
3171
3201
|
|
|
3172
|
-
|
|
3202
|
+
res = json_get_int_param(document, "media_id", true, &media_id);
|
|
3203
|
+
if (res <= 0) {
|
|
3204
|
+
goto out;
|
|
3205
|
+
}
|
|
3206
|
+
|
|
3207
|
+
if (NOT_FOUND_OPTIONAL == res) {
|
|
3208
|
+
// send_dtmf to all audio endpoints
|
|
3209
|
+
status = send_dtmf(call, adjusted_digits, mode);
|
|
3210
|
+
if (status != PJ_SUCCESS) {
|
|
3211
|
+
goto out;
|
|
3212
|
+
}
|
|
3213
|
+
} else {
|
|
3214
|
+
// send_dtmf to specified media_id
|
|
3215
|
+
|
|
3216
|
+
if (media_id >= call->media_count) {
|
|
3217
|
+
set_error("invalid media_id");
|
|
3218
|
+
goto out;
|
|
3219
|
+
}
|
|
3220
|
+
|
|
3221
|
+
me = (MediaEndpoint *)call->media[media_id];
|
|
3222
|
+
if (ENDPOINT_TYPE_AUDIO != me->type) {
|
|
3223
|
+
set_error("invalid media_id non audio");
|
|
3224
|
+
goto out;
|
|
3225
|
+
}
|
|
3226
|
+
|
|
3227
|
+
ae = (AudioEndpoint *)me->endpoint.audio;
|
|
3228
|
+
|
|
3229
|
+
status = audio_endpoint_send_dtmf(call, ae, digits, mode);
|
|
3230
|
+
if (status != PJ_SUCCESS) {
|
|
3231
|
+
goto out;
|
|
3232
|
+
}
|
|
3233
|
+
}
|
|
3173
3234
|
|
|
3174
3235
|
out:
|
|
3175
3236
|
PJW_UNLOCK();
|
|
@@ -3180,7 +3241,7 @@ out:
|
|
|
3180
3241
|
return 0;
|
|
3181
3242
|
}
|
|
3182
3243
|
|
|
3183
|
-
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) {
|
|
3184
3245
|
printf("audio_endpoint_remove_port\n");
|
|
3185
3246
|
pj_status_t status;
|
|
3186
3247
|
|
|
@@ -3191,7 +3252,7 @@ pj_status_t audio_endpoint_remove_port(Call *call, ConfBridgePort *cbp) {
|
|
|
3191
3252
|
pjmedia_conf_disconnect_port_from_sinks(conf, port);
|
|
3192
3253
|
*/
|
|
3193
3254
|
|
|
3194
|
-
status = pjmedia_conf_remove_port(
|
|
3255
|
+
status = pjmedia_conf_remove_port(ae->conf, cbp->slot);
|
|
3195
3256
|
if (status != PJ_SUCCESS) {
|
|
3196
3257
|
set_error("pjmedia_conf_remove_port failed");
|
|
3197
3258
|
return false;
|
|
@@ -3443,7 +3504,15 @@ int count_media_by_type(Call *call, int type) {
|
|
|
3443
3504
|
return total;
|
|
3444
3505
|
}
|
|
3445
3506
|
|
|
3446
|
-
|
|
3507
|
+
int get_first_media_id_by_type(Call *call, int type) {
|
|
3508
|
+
for (int i = 0; i < call->media_count; i++) {
|
|
3509
|
+
MediaEndpoint *me = (MediaEndpoint *)call->media[i];
|
|
3510
|
+
if (type == me->type)
|
|
3511
|
+
return i;
|
|
3512
|
+
}
|
|
3513
|
+
return -1;
|
|
3514
|
+
}
|
|
3515
|
+
|
|
3447
3516
|
int pjw_call_start_record_wav(long call_id, const char *json) {
|
|
3448
3517
|
PJW_LOCK();
|
|
3449
3518
|
clear_error();
|
|
@@ -3452,7 +3521,7 @@ int pjw_call_start_record_wav(long call_id, const char *json) {
|
|
|
3452
3521
|
Call *call;
|
|
3453
3522
|
pj_status_t status;
|
|
3454
3523
|
|
|
3455
|
-
|
|
3524
|
+
int media_id = -1;
|
|
3456
3525
|
|
|
3457
3526
|
MediaEndpoint *me;
|
|
3458
3527
|
AudioEndpoint *ae;
|
|
@@ -3497,7 +3566,13 @@ int pjw_call_start_record_wav(long call_id, const char *json) {
|
|
|
3497
3566
|
}
|
|
3498
3567
|
|
|
3499
3568
|
if (ae_count > 1) {
|
|
3500
|
-
if (
|
|
3569
|
+
if (json_get_int_param(document, "media_id", false, &media_id) <= 0) {
|
|
3570
|
+
goto out;
|
|
3571
|
+
}
|
|
3572
|
+
} else {
|
|
3573
|
+
media_id = get_first_media_id_by_type(call, ENDPOINT_TYPE_AUDIO);
|
|
3574
|
+
if(media_id < 0) {
|
|
3575
|
+
set_error("could not resolve media_id");
|
|
3501
3576
|
goto out;
|
|
3502
3577
|
}
|
|
3503
3578
|
}
|
|
@@ -3541,7 +3616,7 @@ out:
|
|
|
3541
3616
|
}
|
|
3542
3617
|
|
|
3543
3618
|
pj_status_t audio_endpoint_start_play_wav(Call *call, AudioEndpoint *ae,
|
|
3544
|
-
const char *file) {
|
|
3619
|
+
const char *file, unsigned flags, bool end_of_file_event) {
|
|
3545
3620
|
pj_status_t status;
|
|
3546
3621
|
|
|
3547
3622
|
if(!ae->stream_cbp.port) {
|
|
@@ -3555,14 +3630,34 @@ pj_status_t audio_endpoint_start_play_wav(Call *call, AudioEndpoint *ae,
|
|
|
3555
3630
|
return -1;
|
|
3556
3631
|
}
|
|
3557
3632
|
|
|
3558
|
-
if (!prepare_wav_player(call, ae, file)) {
|
|
3633
|
+
if (!prepare_wav_player(call, ae, file, flags, end_of_file_event)) {
|
|
3634
|
+
return -1;
|
|
3635
|
+
}
|
|
3636
|
+
|
|
3637
|
+
return PJ_SUCCESS;
|
|
3638
|
+
}
|
|
3639
|
+
|
|
3640
|
+
pj_status_t audio_endpoint_start_fax(Call *call, AudioEndpoint *ae, bool is_sender, char *file, unsigned flags) {
|
|
3641
|
+
pj_status_t status;
|
|
3642
|
+
|
|
3643
|
+
if(!ae->stream_cbp.port) {
|
|
3644
|
+
set_error("stream port is not ready yet");
|
|
3645
|
+
return -1;
|
|
3646
|
+
}
|
|
3647
|
+
|
|
3648
|
+
// First stop and destroy existing port.
|
|
3649
|
+
status = audio_endpoint_stop_fax(call, ae);
|
|
3650
|
+
if(status != PJ_SUCCESS) {
|
|
3651
|
+
return -1;
|
|
3652
|
+
}
|
|
3653
|
+
|
|
3654
|
+
if (!prepare_fax(call, ae, is_sender, file, flags)) {
|
|
3559
3655
|
return -1;
|
|
3560
3656
|
}
|
|
3561
3657
|
|
|
3562
3658
|
return PJ_SUCCESS;
|
|
3563
3659
|
}
|
|
3564
3660
|
|
|
3565
|
-
// int pjw_call_start_play_wav(long call_id, const char *file)
|
|
3566
3661
|
int pjw_call_start_play_wav(long call_id, const char *json) {
|
|
3567
3662
|
PJW_LOCK();
|
|
3568
3663
|
clear_error();
|
|
@@ -3573,16 +3668,25 @@ int pjw_call_start_play_wav(long call_id, const char *json) {
|
|
|
3573
3668
|
MediaEndpoint *me;
|
|
3574
3669
|
AudioEndpoint *ae;
|
|
3575
3670
|
int ae_count;
|
|
3671
|
+
int res;
|
|
3576
3672
|
|
|
3577
|
-
|
|
3673
|
+
int media_id = -1;
|
|
3578
3674
|
|
|
3579
3675
|
char *file;
|
|
3580
3676
|
|
|
3677
|
+
unsigned flags = 0;
|
|
3678
|
+
|
|
3679
|
+
bool end_of_file_event = false;
|
|
3680
|
+
|
|
3681
|
+
bool no_loop = false;
|
|
3682
|
+
|
|
3581
3683
|
char buffer[MAX_JSON_INPUT];
|
|
3582
3684
|
|
|
3685
|
+
pj_status_t status;
|
|
3686
|
+
|
|
3583
3687
|
Document document;
|
|
3584
3688
|
|
|
3585
|
-
const char *valid_params[] = {"file", "media_id", ""};
|
|
3689
|
+
const char *valid_params[] = {"file", "media_id", "end_of_file_event", "no_loop", ""};
|
|
3586
3690
|
|
|
3587
3691
|
if (!g_call_ids.get(call_id, val)) {
|
|
3588
3692
|
set_error("Invalid call_id");
|
|
@@ -3614,26 +3718,49 @@ int pjw_call_start_play_wav(long call_id, const char *json) {
|
|
|
3614
3718
|
goto out;
|
|
3615
3719
|
}
|
|
3616
3720
|
|
|
3617
|
-
if (
|
|
3618
|
-
|
|
3619
|
-
goto out;
|
|
3620
|
-
}
|
|
3721
|
+
if (json_get_bool_param(document, "end_of_file_event", true, &end_of_file_event) <= 0) {
|
|
3722
|
+
goto out;
|
|
3621
3723
|
}
|
|
3622
3724
|
|
|
3623
|
-
if ((
|
|
3624
|
-
set_error("invalid media_id");
|
|
3725
|
+
if (json_get_bool_param(document, "no_loop", true, &no_loop) <= 0) {
|
|
3625
3726
|
goto out;
|
|
3626
3727
|
}
|
|
3627
3728
|
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3729
|
+
if(no_loop) {
|
|
3730
|
+
flags |= PJMEDIA_FILE_NO_LOOP;
|
|
3731
|
+
}
|
|
3732
|
+
|
|
3733
|
+
res = json_get_int_param(document, "media_id", true, &media_id);
|
|
3734
|
+
if (res <= 0) {
|
|
3631
3735
|
goto out;
|
|
3632
3736
|
}
|
|
3633
3737
|
|
|
3634
|
-
|
|
3738
|
+
if (NOT_FOUND_OPTIONAL == res) {
|
|
3739
|
+
// start on all audio media endpoints
|
|
3740
|
+
for (int i = 0; i < call->media_count; i++) {
|
|
3741
|
+
MediaEndpoint *me = (MediaEndpoint *)call->media[i];
|
|
3742
|
+
if (me->type == ENDPOINT_TYPE_AUDIO) {
|
|
3743
|
+
AudioEndpoint *ae = (AudioEndpoint *)me->endpoint.audio;
|
|
3744
|
+
status = audio_endpoint_start_play_wav(call, ae, file, flags, end_of_file_event);
|
|
3745
|
+
if (status != PJ_SUCCESS) goto out;
|
|
3746
|
+
}
|
|
3747
|
+
}
|
|
3748
|
+
} else {
|
|
3749
|
+
if (media_id >= call->media_count) {
|
|
3750
|
+
set_error("invalid media_id");
|
|
3751
|
+
goto out;
|
|
3752
|
+
}
|
|
3753
|
+
|
|
3754
|
+
me = (MediaEndpoint *)call->media[media_id];
|
|
3755
|
+
if (ENDPOINT_TYPE_AUDIO != me->type) {
|
|
3756
|
+
set_error("media_endpoint is not audio endpoint");
|
|
3757
|
+
goto out;
|
|
3758
|
+
}
|
|
3635
3759
|
|
|
3636
|
-
|
|
3760
|
+
ae = (AudioEndpoint *)me->endpoint.audio;
|
|
3761
|
+
|
|
3762
|
+
audio_endpoint_start_play_wav(call, ae, file, flags, end_of_file_event);
|
|
3763
|
+
}
|
|
3637
3764
|
|
|
3638
3765
|
out:
|
|
3639
3766
|
PJW_UNLOCK();
|
|
@@ -3644,7 +3771,7 @@ out:
|
|
|
3644
3771
|
return 0;
|
|
3645
3772
|
}
|
|
3646
3773
|
|
|
3647
|
-
pj_status_t audio_endpoint_start_speech_synth(Call *call, AudioEndpoint *ae, const char * voice, const char *text) {
|
|
3774
|
+
pj_status_t audio_endpoint_start_speech_synth(Call *call, AudioEndpoint *ae, const char * voice, const char *text, unsigned flags, bool end_of_speech_event) {
|
|
3648
3775
|
pj_status_t status;
|
|
3649
3776
|
|
|
3650
3777
|
if(!ae->stream_cbp.port) {
|
|
@@ -3653,16 +3780,16 @@ pj_status_t audio_endpoint_start_speech_synth(Call *call, AudioEndpoint *ae, con
|
|
|
3653
3780
|
}
|
|
3654
3781
|
|
|
3655
3782
|
// First stop and destroy existing flite port.
|
|
3656
|
-
status =
|
|
3783
|
+
status = audio_endpoint_stop_speech_synth(call, ae);
|
|
3657
3784
|
if(status != PJ_SUCCESS) {
|
|
3658
3785
|
return -1;
|
|
3659
3786
|
}
|
|
3660
3787
|
|
|
3661
|
-
if (!prepare_flite(call, ae, voice)) {
|
|
3788
|
+
if (!prepare_flite(call, ae, voice, end_of_speech_event)) {
|
|
3662
3789
|
return -1;
|
|
3663
3790
|
}
|
|
3664
3791
|
|
|
3665
|
-
pjmedia_flite_port_speak(ae->flite_cbp.port, text,
|
|
3792
|
+
pjmedia_flite_port_speak(ae->flite_cbp.port, text, flags);
|
|
3666
3793
|
|
|
3667
3794
|
return PJ_SUCCESS;
|
|
3668
3795
|
}
|
|
@@ -3674,21 +3801,30 @@ int pjw_call_start_speech_synth(long call_id, const char *json) {
|
|
|
3674
3801
|
long val;
|
|
3675
3802
|
Call *call;
|
|
3676
3803
|
|
|
3804
|
+
pj_status_t status;
|
|
3805
|
+
|
|
3677
3806
|
MediaEndpoint *me;
|
|
3678
3807
|
AudioEndpoint *ae;
|
|
3679
3808
|
int ae_count;
|
|
3809
|
+
int res;
|
|
3680
3810
|
|
|
3681
|
-
|
|
3811
|
+
int media_id = -1;
|
|
3682
3812
|
|
|
3683
3813
|
char *voice;
|
|
3684
3814
|
|
|
3685
3815
|
char *text;
|
|
3686
3816
|
|
|
3817
|
+
bool end_of_speech_event = false;
|
|
3818
|
+
|
|
3819
|
+
unsigned flags = 0;
|
|
3820
|
+
|
|
3821
|
+
bool no_loop = false;
|
|
3822
|
+
|
|
3687
3823
|
char buffer[MAX_JSON_INPUT];
|
|
3688
3824
|
|
|
3689
3825
|
Document document;
|
|
3690
3826
|
|
|
3691
|
-
const char *valid_params[] = {"voice", "text", "media_id", ""};
|
|
3827
|
+
const char *valid_params[] = {"voice", "text", "media_id", "end_of_speech_event", "no_loop", ""};
|
|
3692
3828
|
|
|
3693
3829
|
if (!g_call_ids.get(call_id, val)) {
|
|
3694
3830
|
set_error("Invalid call_id");
|
|
@@ -3729,26 +3865,49 @@ int pjw_call_start_speech_synth(long call_id, const char *json) {
|
|
|
3729
3865
|
goto out;
|
|
3730
3866
|
}
|
|
3731
3867
|
|
|
3732
|
-
if (
|
|
3733
|
-
|
|
3734
|
-
goto out;
|
|
3735
|
-
}
|
|
3868
|
+
if (json_get_bool_param(document, "end_of_speech_event", true, &end_of_speech_event) <= 0) {
|
|
3869
|
+
goto out;
|
|
3736
3870
|
}
|
|
3737
3871
|
|
|
3738
|
-
if ((
|
|
3739
|
-
set_error("invalid media_id");
|
|
3872
|
+
if (json_get_bool_param(document, "no_loop", true, &no_loop) <= 0) {
|
|
3740
3873
|
goto out;
|
|
3741
3874
|
}
|
|
3742
3875
|
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3876
|
+
if(no_loop) {
|
|
3877
|
+
flags |= PJMEDIA_SPEECH_NO_LOOP;
|
|
3878
|
+
}
|
|
3879
|
+
|
|
3880
|
+
res = json_get_int_param(document, "media_id", true, &media_id);
|
|
3881
|
+
if (res <= 0) {
|
|
3746
3882
|
goto out;
|
|
3747
3883
|
}
|
|
3748
3884
|
|
|
3749
|
-
|
|
3885
|
+
if (NOT_FOUND_OPTIONAL == res) {
|
|
3886
|
+
// start on all audio media endpoints
|
|
3887
|
+
for (int i = 0; i < call->media_count; i++) {
|
|
3888
|
+
MediaEndpoint *me = (MediaEndpoint *)call->media[i];
|
|
3889
|
+
if (me->type == ENDPOINT_TYPE_AUDIO) {
|
|
3890
|
+
AudioEndpoint *ae = (AudioEndpoint *)me->endpoint.audio;
|
|
3891
|
+
status = audio_endpoint_start_speech_synth(call, ae, voice, text, flags, end_of_speech_event);
|
|
3892
|
+
if (status != PJ_SUCCESS) goto out;
|
|
3893
|
+
}
|
|
3894
|
+
}
|
|
3895
|
+
} else {
|
|
3896
|
+
if ((int)media_id >= call->media_count) {
|
|
3897
|
+
set_error("invalid media_id");
|
|
3898
|
+
goto out;
|
|
3899
|
+
}
|
|
3900
|
+
|
|
3901
|
+
me = (MediaEndpoint *)call->media[media_id];
|
|
3902
|
+
if (ENDPOINT_TYPE_AUDIO != me->type) {
|
|
3903
|
+
set_error("media_endpoint is not audio endpoint");
|
|
3904
|
+
goto out;
|
|
3905
|
+
}
|
|
3750
3906
|
|
|
3751
|
-
|
|
3907
|
+
ae = (AudioEndpoint *)me->endpoint.audio;
|
|
3908
|
+
|
|
3909
|
+
audio_endpoint_start_speech_synth(call, ae, voice, text, flags, end_of_speech_event);
|
|
3910
|
+
}
|
|
3752
3911
|
|
|
3753
3912
|
out:
|
|
3754
3913
|
PJW_UNLOCK();
|
|
@@ -3759,79 +3918,96 @@ out:
|
|
|
3759
3918
|
return 0;
|
|
3760
3919
|
}
|
|
3761
3920
|
|
|
3762
|
-
pj_status_t
|
|
3763
|
-
return audio_endpoint_remove_port(call, &ae->flite_cbp);
|
|
3764
|
-
}
|
|
3765
|
-
|
|
3766
|
-
pj_status_t call_stop_audio_endpoints_op(Call *call,
|
|
3767
|
-
audio_endpoint_stop_op_t op) {
|
|
3768
|
-
addon_log(L_DBG, "call_stop_audio_endpoints_op media_count=%d\n",
|
|
3769
|
-
call->media_count);
|
|
3921
|
+
pj_status_t audio_endpoint_start_speech_recog(Call *call, AudioEndpoint *ae) {
|
|
3770
3922
|
pj_status_t status;
|
|
3771
|
-
for (int i = 0; i < call->media_count; i++) {
|
|
3772
|
-
MediaEndpoint *me = (MediaEndpoint *)call->media[i];
|
|
3773
|
-
if (ENDPOINT_TYPE_AUDIO != me->type)
|
|
3774
|
-
continue;
|
|
3775
3923
|
|
|
3776
|
-
|
|
3924
|
+
if(!ae->stream_cbp.port) {
|
|
3925
|
+
set_error("stream port is not ready yet");
|
|
3926
|
+
return -1;
|
|
3927
|
+
}
|
|
3777
3928
|
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
|
|
3781
|
-
|
|
3929
|
+
// First stop and destroy existing port.
|
|
3930
|
+
status = audio_endpoint_stop_speech_recog(call, ae);
|
|
3931
|
+
if(status != PJ_SUCCESS) {
|
|
3932
|
+
return -1;
|
|
3782
3933
|
}
|
|
3783
3934
|
|
|
3784
|
-
|
|
3785
|
-
|
|
3935
|
+
if (!prepare_pocketsphinx(call, ae)) {
|
|
3936
|
+
return -1;
|
|
3937
|
+
}
|
|
3786
3938
|
|
|
3787
|
-
|
|
3788
|
-
return audio_endpoint_remove_port(call, &ae->wav_player_cbp);
|
|
3939
|
+
return PJ_SUCCESS;
|
|
3789
3940
|
}
|
|
3790
3941
|
|
|
3791
|
-
int
|
|
3942
|
+
int pjw_call_start_speech_recog(long call_id, const char *json) {
|
|
3792
3943
|
PJW_LOCK();
|
|
3793
3944
|
clear_error();
|
|
3794
3945
|
|
|
3946
|
+
long val;
|
|
3795
3947
|
Call *call;
|
|
3796
3948
|
|
|
3797
3949
|
pj_status_t status;
|
|
3798
3950
|
|
|
3799
|
-
long val;
|
|
3800
|
-
|
|
3801
3951
|
MediaEndpoint *me;
|
|
3802
3952
|
AudioEndpoint *ae;
|
|
3953
|
+
int ae_count;
|
|
3803
3954
|
int res;
|
|
3804
3955
|
|
|
3805
|
-
|
|
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;
|
|
3806
3967
|
|
|
3807
3968
|
char buffer[MAX_JSON_INPUT];
|
|
3808
3969
|
|
|
3809
3970
|
Document document;
|
|
3810
3971
|
|
|
3972
|
+
const char *valid_params[] = {"media_id", ""};
|
|
3973
|
+
|
|
3811
3974
|
if (!g_call_ids.get(call_id, val)) {
|
|
3812
3975
|
set_error("Invalid call_id");
|
|
3813
3976
|
goto out;
|
|
3814
3977
|
}
|
|
3815
3978
|
call = (Call *)val;
|
|
3816
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
|
+
|
|
3817
3987
|
if (!parse_json(document, json, buffer, MAX_JSON_INPUT)) {
|
|
3818
3988
|
goto out;
|
|
3819
3989
|
}
|
|
3820
3990
|
|
|
3821
|
-
|
|
3991
|
+
if (!validate_params(document, valid_params)) {
|
|
3992
|
+
goto out;
|
|
3993
|
+
}
|
|
3994
|
+
|
|
3995
|
+
res = json_get_int_param(document, "media_id", true, &media_id);
|
|
3822
3996
|
if (res <= 0) {
|
|
3823
3997
|
goto out;
|
|
3824
3998
|
}
|
|
3825
3999
|
|
|
3826
4000
|
if (NOT_FOUND_OPTIONAL == res) {
|
|
3827
|
-
//
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
|
|
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
|
+
}
|
|
3831
4009
|
}
|
|
3832
4010
|
} else {
|
|
3833
|
-
// Stop play wav on specified media_id
|
|
3834
|
-
|
|
3835
4011
|
if ((int)media_id >= call->media_count) {
|
|
3836
4012
|
set_error("invalid media_id");
|
|
3837
4013
|
goto out;
|
|
@@ -3839,16 +4015,13 @@ int pjw_call_stop_play_wav(long call_id, const char *json) {
|
|
|
3839
4015
|
|
|
3840
4016
|
me = (MediaEndpoint *)call->media[media_id];
|
|
3841
4017
|
if (ENDPOINT_TYPE_AUDIO != me->type) {
|
|
3842
|
-
set_error("
|
|
4018
|
+
set_error("media_endpoint is not audio endpoint");
|
|
3843
4019
|
goto out;
|
|
3844
4020
|
}
|
|
3845
4021
|
|
|
3846
4022
|
ae = (AudioEndpoint *)me->endpoint.audio;
|
|
3847
4023
|
|
|
3848
|
-
|
|
3849
|
-
if (status != PJ_SUCCESS) {
|
|
3850
|
-
goto out;
|
|
3851
|
-
}
|
|
4024
|
+
audio_endpoint_start_speech_recog(call, ae);
|
|
3852
4025
|
}
|
|
3853
4026
|
|
|
3854
4027
|
out:
|
|
@@ -3860,23 +4033,42 @@ out:
|
|
|
3860
4033
|
return 0;
|
|
3861
4034
|
}
|
|
3862
4035
|
|
|
3863
|
-
pj_status_t
|
|
3864
|
-
|
|
4036
|
+
pj_status_t call_stop_op_on_all_audio_endpoints(Call *call,
|
|
4037
|
+
audio_endpoint_stop_op_t op) {
|
|
4038
|
+
addon_log(L_DBG, "call_stop_op_on_audio_endpoints media_count=%d\n",
|
|
4039
|
+
call->media_count);
|
|
4040
|
+
pj_status_t status;
|
|
4041
|
+
for (int i = 0; i < call->media_count; i++) {
|
|
4042
|
+
MediaEndpoint *me = (MediaEndpoint *)call->media[i];
|
|
4043
|
+
if (ENDPOINT_TYPE_AUDIO != me->type)
|
|
4044
|
+
continue;
|
|
4045
|
+
|
|
4046
|
+
AudioEndpoint *ae = (AudioEndpoint *)me->endpoint.audio;
|
|
4047
|
+
|
|
4048
|
+
status = op(call, ae);
|
|
4049
|
+
if (status != PJ_SUCCESS) {
|
|
4050
|
+
return status;
|
|
4051
|
+
}
|
|
4052
|
+
}
|
|
4053
|
+
|
|
4054
|
+
return PJ_SUCCESS;
|
|
3865
4055
|
}
|
|
3866
4056
|
|
|
3867
|
-
int
|
|
4057
|
+
int audio_endpoint_stop_op(long call_id, const char *json, audio_endpoint_stop_op_t op) {
|
|
3868
4058
|
PJW_LOCK();
|
|
3869
4059
|
clear_error();
|
|
3870
4060
|
|
|
3871
|
-
|
|
3872
|
-
|
|
4061
|
+
Call *call;
|
|
4062
|
+
|
|
3873
4063
|
pj_status_t status;
|
|
3874
4064
|
|
|
4065
|
+
long val;
|
|
4066
|
+
|
|
3875
4067
|
MediaEndpoint *me;
|
|
3876
4068
|
AudioEndpoint *ae;
|
|
3877
4069
|
int res;
|
|
3878
4070
|
|
|
3879
|
-
|
|
4071
|
+
int media_id = -1;
|
|
3880
4072
|
|
|
3881
4073
|
char buffer[MAX_JSON_INPUT];
|
|
3882
4074
|
|
|
@@ -3892,21 +4084,19 @@ int pjw_call_stop_record_wav(long call_id, const char *json) {
|
|
|
3892
4084
|
goto out;
|
|
3893
4085
|
}
|
|
3894
4086
|
|
|
3895
|
-
res =
|
|
4087
|
+
res = json_get_int_param(document, "media_id", true, &media_id);
|
|
3896
4088
|
if (res <= 0) {
|
|
3897
4089
|
goto out;
|
|
3898
4090
|
}
|
|
3899
4091
|
|
|
3900
4092
|
if (NOT_FOUND_OPTIONAL == res) {
|
|
3901
|
-
// Stop
|
|
3902
|
-
status =
|
|
3903
|
-
if (status != PJ_SUCCESS)
|
|
3904
|
-
goto out;
|
|
3905
|
-
}
|
|
4093
|
+
// Stop op on all audio endpoints
|
|
4094
|
+
status = call_stop_op_on_all_audio_endpoints(call, op);
|
|
4095
|
+
if (status != PJ_SUCCESS) goto out;
|
|
3906
4096
|
} else {
|
|
3907
|
-
// Stop
|
|
4097
|
+
// Stop op on specified media
|
|
3908
4098
|
|
|
3909
|
-
if (
|
|
4099
|
+
if (media_id >= call->media_count) {
|
|
3910
4100
|
set_error("invalid media_id");
|
|
3911
4101
|
goto out;
|
|
3912
4102
|
}
|
|
@@ -3919,10 +4109,8 @@ int pjw_call_stop_record_wav(long call_id, const char *json) {
|
|
|
3919
4109
|
|
|
3920
4110
|
ae = (AudioEndpoint *)me->endpoint.audio;
|
|
3921
4111
|
|
|
3922
|
-
status =
|
|
3923
|
-
if (status != PJ_SUCCESS)
|
|
3924
|
-
goto out;
|
|
3925
|
-
}
|
|
4112
|
+
status = op(call, ae);
|
|
4113
|
+
if (status != PJ_SUCCESS) goto out;
|
|
3926
4114
|
}
|
|
3927
4115
|
|
|
3928
4116
|
out:
|
|
@@ -3934,152 +4122,74 @@ out:
|
|
|
3934
4122
|
return 0;
|
|
3935
4123
|
}
|
|
3936
4124
|
|
|
3937
|
-
pj_status_t
|
|
3938
|
-
return audio_endpoint_remove_port(call, &ae->
|
|
4125
|
+
pj_status_t audio_endpoint_stop_speech_synth(Call *call, AudioEndpoint *ae) {
|
|
4126
|
+
return audio_endpoint_remove_port(call, ae, &ae->flite_cbp);
|
|
3939
4127
|
}
|
|
3940
4128
|
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
|
|
3945
|
-
long val;
|
|
3946
|
-
Call *call;
|
|
3947
|
-
pj_status_t status;
|
|
3948
|
-
|
|
3949
|
-
bool is_sender;
|
|
3950
|
-
char *file;
|
|
3951
|
-
unsigned flags = 0;
|
|
3952
|
-
bool flag;
|
|
3953
|
-
|
|
3954
|
-
MediaEndpoint *me;
|
|
3955
|
-
AudioEndpoint *ae;
|
|
3956
|
-
int ae_count;
|
|
3957
|
-
|
|
3958
|
-
unsigned media_id = 0;
|
|
3959
|
-
|
|
3960
|
-
char buffer[MAX_JSON_INPUT];
|
|
3961
|
-
|
|
3962
|
-
const char *valid_params[] = {"is_sender", "file", "transmit_on_idle",
|
|
3963
|
-
"media_id", ""};
|
|
3964
|
-
|
|
3965
|
-
Document document;
|
|
3966
|
-
|
|
3967
|
-
if (!g_call_ids.get(call_id, val)) {
|
|
3968
|
-
set_error("Invalid call_id");
|
|
3969
|
-
goto out;
|
|
3970
|
-
}
|
|
3971
|
-
call = (Call *)val;
|
|
3972
|
-
|
|
3973
|
-
ae_count = count_media_by_type(call, ENDPOINT_TYPE_AUDIO);
|
|
3974
|
-
|
|
3975
|
-
if (ae_count == 0) {
|
|
3976
|
-
set_error("No audio endpoint");
|
|
3977
|
-
goto out;
|
|
3978
|
-
}
|
|
3979
|
-
|
|
3980
|
-
if (!parse_json(document, json, buffer, MAX_JSON_INPUT)) {
|
|
3981
|
-
goto out;
|
|
3982
|
-
}
|
|
3983
|
-
|
|
3984
|
-
if (!validate_params(document, valid_params)) {
|
|
3985
|
-
goto out;
|
|
3986
|
-
}
|
|
3987
|
-
|
|
3988
|
-
if (json_get_string_param(document, "file", false, &file) <= 0) {
|
|
3989
|
-
goto out;
|
|
3990
|
-
}
|
|
3991
|
-
|
|
3992
|
-
if (!file[0]) {
|
|
3993
|
-
set_error("file cannot be blank string");
|
|
3994
|
-
goto out;
|
|
3995
|
-
}
|
|
3996
|
-
|
|
3997
|
-
if (ae_count > 1) {
|
|
3998
|
-
if (json_get_uint_param(document, "media_id", false, &media_id) <= 0) {
|
|
3999
|
-
goto out;
|
|
4000
|
-
}
|
|
4001
|
-
}
|
|
4002
|
-
|
|
4003
|
-
if ((int)media_id >= call->media_count) {
|
|
4004
|
-
set_error("invalid media_id");
|
|
4005
|
-
goto out;
|
|
4006
|
-
}
|
|
4007
|
-
|
|
4008
|
-
me = (MediaEndpoint *)call->media[media_id];
|
|
4009
|
-
if (ENDPOINT_TYPE_AUDIO != me->type) {
|
|
4010
|
-
set_error("media_endpoint is not audio endpoint");
|
|
4011
|
-
goto out;
|
|
4012
|
-
}
|
|
4013
|
-
|
|
4014
|
-
ae = (AudioEndpoint *)me->endpoint.audio;
|
|
4015
|
-
|
|
4016
|
-
if (!parse_json(document, json, buffer, MAX_JSON_INPUT)) {
|
|
4017
|
-
goto out;
|
|
4018
|
-
}
|
|
4019
|
-
|
|
4020
|
-
if (!validate_params(document, valid_params)) {
|
|
4021
|
-
goto out;
|
|
4022
|
-
}
|
|
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
|
+
}
|
|
4023
4132
|
|
|
4024
|
-
|
|
4025
|
-
|
|
4026
|
-
|
|
4133
|
+
pj_status_t audio_endpoint_stop_play_wav(Call *call, AudioEndpoint *ae) {
|
|
4134
|
+
return audio_endpoint_remove_port(call, ae, &ae->wav_player_cbp);
|
|
4135
|
+
}
|
|
4027
4136
|
|
|
4028
|
-
|
|
4029
|
-
|
|
4030
|
-
|
|
4137
|
+
pj_status_t audio_endpoint_stop_record_wav(Call *call, AudioEndpoint *ae) {
|
|
4138
|
+
return audio_endpoint_remove_port(call, ae, &ae->wav_writer_cbp);
|
|
4139
|
+
}
|
|
4031
4140
|
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
}
|
|
4141
|
+
pj_status_t audio_endpoint_stop_fax(Call *call, AudioEndpoint *ae) {
|
|
4142
|
+
return audio_endpoint_remove_port(call, ae, &ae->fax_cbp);
|
|
4143
|
+
}
|
|
4036
4144
|
|
|
4037
|
-
flag = false;
|
|
4038
|
-
if (json_get_bool_param(document, "transmit_on_idle", true, &flag) <= 0) {
|
|
4039
|
-
goto out;
|
|
4040
|
-
} else {
|
|
4041
|
-
if (flag)
|
|
4042
|
-
flags |= FAX_FLAG_TRANSMIT_ON_IDLE;
|
|
4043
|
-
}
|
|
4044
4145
|
|
|
4045
|
-
// First stop and destroy existing fax port.
|
|
4046
|
-
status = audio_endpoint_stop_fax(call, ae);
|
|
4047
|
-
if(status != PJ_SUCCESS) {
|
|
4048
|
-
set_error("audio_endpoint_stop_fax failed");
|
|
4049
|
-
return -1;
|
|
4050
|
-
}
|
|
4051
4146
|
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
}
|
|
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);
|
|
4149
|
+
}
|
|
4056
4150
|
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
return -1;
|
|
4061
|
-
}
|
|
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
|
+
}
|
|
4062
4154
|
|
|
4063
|
-
|
|
4155
|
+
int pjw_call_stop_play_wav(long call_id, const char *json) {
|
|
4156
|
+
return audio_endpoint_stop_op(call_id, json, audio_endpoint_stop_play_wav);
|
|
4157
|
+
}
|
|
4158
|
+
|
|
4159
|
+
int pjw_call_stop_record_wav(long call_id, const char *json) {
|
|
4160
|
+
return audio_endpoint_stop_op(call_id, json, audio_endpoint_stop_record_wav);
|
|
4064
4161
|
}
|
|
4065
4162
|
|
|
4066
4163
|
int pjw_call_stop_fax(long call_id, const char *json) {
|
|
4164
|
+
return audio_endpoint_stop_op(call_id, json, audio_endpoint_stop_fax);
|
|
4165
|
+
}
|
|
4166
|
+
|
|
4167
|
+
|
|
4168
|
+
int pjw_call_start_fax(long call_id, const char *json) {
|
|
4067
4169
|
PJW_LOCK();
|
|
4068
4170
|
clear_error();
|
|
4069
4171
|
|
|
4070
4172
|
long val;
|
|
4071
4173
|
Call *call;
|
|
4072
|
-
|
|
4073
4174
|
pj_status_t status;
|
|
4074
4175
|
|
|
4176
|
+
bool is_sender;
|
|
4177
|
+
char *file;
|
|
4178
|
+
unsigned flags = 0;
|
|
4179
|
+
bool flag;
|
|
4180
|
+
|
|
4075
4181
|
MediaEndpoint *me;
|
|
4076
4182
|
AudioEndpoint *ae;
|
|
4183
|
+
int ae_count;
|
|
4077
4184
|
int res;
|
|
4078
4185
|
|
|
4079
|
-
|
|
4186
|
+
int media_id = -1;
|
|
4080
4187
|
|
|
4081
4188
|
char buffer[MAX_JSON_INPUT];
|
|
4082
4189
|
|
|
4190
|
+
const char *valid_params[] = {"is_sender", "file", "transmit_on_idle",
|
|
4191
|
+
"media_id", ""};
|
|
4192
|
+
|
|
4083
4193
|
Document document;
|
|
4084
4194
|
|
|
4085
4195
|
if (!g_call_ids.get(call_id, val)) {
|
|
@@ -4088,27 +4198,86 @@ int pjw_call_stop_fax(long call_id, const char *json) {
|
|
|
4088
4198
|
}
|
|
4089
4199
|
call = (Call *)val;
|
|
4090
4200
|
|
|
4201
|
+
ae_count = count_media_by_type(call, ENDPOINT_TYPE_AUDIO);
|
|
4202
|
+
|
|
4203
|
+
if (ae_count == 0) {
|
|
4204
|
+
set_error("No audio endpoint");
|
|
4205
|
+
goto out;
|
|
4206
|
+
}
|
|
4207
|
+
|
|
4091
4208
|
if (!parse_json(document, json, buffer, MAX_JSON_INPUT)) {
|
|
4092
4209
|
goto out;
|
|
4093
4210
|
}
|
|
4094
4211
|
|
|
4095
|
-
|
|
4096
|
-
if (res <= 0) {
|
|
4212
|
+
if (!validate_params(document, valid_params)) {
|
|
4097
4213
|
goto out;
|
|
4098
4214
|
}
|
|
4099
4215
|
|
|
4100
|
-
if (
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
|
|
4216
|
+
if (json_get_string_param(document, "file", false, &file) <= 0) {
|
|
4217
|
+
goto out;
|
|
4218
|
+
}
|
|
4219
|
+
|
|
4220
|
+
if (!file[0]) {
|
|
4221
|
+
set_error("file cannot be blank string");
|
|
4222
|
+
goto out;
|
|
4223
|
+
}
|
|
4224
|
+
|
|
4225
|
+
if (json_get_bool_param(document, "is_sender", false, &is_sender) <= 0) {
|
|
4226
|
+
goto out;
|
|
4227
|
+
}
|
|
4228
|
+
|
|
4229
|
+
flag = false;
|
|
4230
|
+
if (json_get_bool_param(document, "transmit_on_idle", true, &flag) <= 0) {
|
|
4231
|
+
goto out;
|
|
4106
4232
|
} else {
|
|
4107
|
-
|
|
4233
|
+
if (flag)
|
|
4234
|
+
flags |= FAX_FLAG_TRANSMIT_ON_IDLE;
|
|
4235
|
+
}
|
|
4108
4236
|
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4237
|
+
if(is_sender) {
|
|
4238
|
+
// if we are sender we can do fax operaton to all media streams
|
|
4239
|
+
res = json_get_int_param(document, "media_id", true, &media_id);
|
|
4240
|
+
if (res <= 0) goto out;
|
|
4241
|
+
|
|
4242
|
+
if (NOT_FOUND_OPTIONAL == res) {
|
|
4243
|
+
// start fax on all audio endpoints
|
|
4244
|
+
for (int i = 0; i < call->media_count; i++) {
|
|
4245
|
+
MediaEndpoint *me = (MediaEndpoint *)call->media[i];
|
|
4246
|
+
if (ENDPOINT_TYPE_AUDIO == me->type) {
|
|
4247
|
+
me = (MediaEndpoint *)call->media[i];
|
|
4248
|
+
ae = (AudioEndpoint *)me->endpoint.audio;
|
|
4249
|
+
status = audio_endpoint_start_fax(call, ae, is_sender, file, flags);
|
|
4250
|
+
if(status != PJ_SUCCESS) goto out;
|
|
4251
|
+
}
|
|
4252
|
+
}
|
|
4253
|
+
} else {
|
|
4254
|
+
if ((int)media_id >= call->media_count) {
|
|
4255
|
+
set_error("invalid media_id");
|
|
4256
|
+
goto out;
|
|
4257
|
+
}
|
|
4258
|
+
|
|
4259
|
+
me = (MediaEndpoint *)call->media[media_id];
|
|
4260
|
+
if (ENDPOINT_TYPE_AUDIO != me->type) {
|
|
4261
|
+
set_error("invalid media_id non audio");
|
|
4262
|
+
goto out;
|
|
4263
|
+
}
|
|
4264
|
+
|
|
4265
|
+
ae = (AudioEndpoint *)me->endpoint.audio;
|
|
4266
|
+
|
|
4267
|
+
status = audio_endpoint_start_fax(call, ae, is_sender, file, flags);
|
|
4268
|
+
if (status != PJ_SUCCESS) goto out;
|
|
4269
|
+
}
|
|
4270
|
+
} else {
|
|
4271
|
+
// if we are not sender we can only start fax operation in a single media endpoint (otherwise, there would be more than one fax process writing to the same fax file)
|
|
4272
|
+
res = json_get_int_param(document, "media_id", true, &media_id);
|
|
4273
|
+
if (res <= 0) goto out;
|
|
4274
|
+
|
|
4275
|
+
if (NOT_FOUND_OPTIONAL == res) {
|
|
4276
|
+
media_id = get_first_media_id_by_type(call, ENDPOINT_TYPE_AUDIO);
|
|
4277
|
+
if(media_id < 0) {
|
|
4278
|
+
set_error("could not resolve media_id");
|
|
4279
|
+
goto out;
|
|
4280
|
+
}
|
|
4112
4281
|
}
|
|
4113
4282
|
|
|
4114
4283
|
me = (MediaEndpoint *)call->media[media_id];
|
|
@@ -4119,10 +4288,11 @@ int pjw_call_stop_fax(long call_id, const char *json) {
|
|
|
4119
4288
|
|
|
4120
4289
|
ae = (AudioEndpoint *)me->endpoint.audio;
|
|
4121
4290
|
|
|
4291
|
+
// First stop and destroy existing fax port.
|
|
4122
4292
|
status = audio_endpoint_stop_fax(call, ae);
|
|
4123
|
-
if
|
|
4124
|
-
|
|
4125
|
-
|
|
4293
|
+
if(status != PJ_SUCCESS) goto out;
|
|
4294
|
+
|
|
4295
|
+
if (!prepare_fax(call, ae, is_sender, file, flags)) goto out;
|
|
4126
4296
|
}
|
|
4127
4297
|
|
|
4128
4298
|
out:
|
|
@@ -4466,82 +4636,80 @@ bool start_tcp_media(Call *call, MediaEndpoint *me,
|
|
|
4466
4636
|
return true;
|
|
4467
4637
|
}
|
|
4468
4638
|
|
|
4639
|
+
void close_audio_endpoint_ports_and_conf(Call *call, AudioEndpoint *ae) {
|
|
4640
|
+
pj_status_t status;
|
|
4469
4641
|
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
|
|
4488
|
-
|
|
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;
|
|
4489
4661
|
}
|
|
4490
4662
|
|
|
4491
|
-
if(ae->
|
|
4492
|
-
|
|
4493
|
-
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
return false;
|
|
4498
|
-
}
|
|
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;
|
|
4499
4669
|
}
|
|
4500
4670
|
|
|
4501
|
-
if(ae->
|
|
4502
|
-
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
return false;
|
|
4508
|
-
}
|
|
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;
|
|
4509
4677
|
}
|
|
4678
|
+
}
|
|
4510
4679
|
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
if (status != PJ_SUCCESS) {
|
|
4514
|
-
make_evt_media_update(evt, sizeof(evt), call->id,
|
|
4515
|
-
"setup_failed (pjmedia_conf_disconnect_port fax dst failed)", "");
|
|
4516
|
-
dispatch_event(evt);
|
|
4517
|
-
return false;
|
|
4518
|
-
}
|
|
4519
|
-
|
|
4520
|
-
status = pjmedia_conf_disconnect_port(call->conf, ae->fax_cbp.slot, ae->stream_cbp.slot);
|
|
4521
|
-
if (status != PJ_SUCCESS) {
|
|
4522
|
-
make_evt_media_update(evt, sizeof(evt), call->id,
|
|
4523
|
-
"setup_failed (pjmedia_conf_disconnect_port for fax src failed)", "");
|
|
4524
|
-
dispatch_event(evt);
|
|
4525
|
-
return false;
|
|
4526
|
-
}
|
|
4527
|
-
}
|
|
4680
|
+
bool connect_feature_port_to_stream_port(Call *call, AudioEndpoint *ae, ConfBridgePort *cbp, int connection_mode) {
|
|
4681
|
+
pj_status_t status;
|
|
4528
4682
|
|
|
4529
|
-
|
|
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);
|
|
4530
4685
|
if (status != PJ_SUCCESS) {
|
|
4531
|
-
|
|
4532
|
-
"setup_failed (pjmedia_conf_remove_port failed)", "");
|
|
4686
|
+
set_error("pjmedia_conf_connect_port failed");
|
|
4533
4687
|
return false;
|
|
4534
4688
|
}
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
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);
|
|
4538
4693
|
if (status != PJ_SUCCESS) {
|
|
4539
|
-
|
|
4540
|
-
"setup_failed (pjmedia_port_destroy failed)", "");
|
|
4694
|
+
set_error("pjmedia_conf_connect_port failed");
|
|
4541
4695
|
return false;
|
|
4542
4696
|
}
|
|
4543
|
-
|
|
4544
|
-
|
|
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;
|
|
4545
4713
|
|
|
4546
4714
|
status =
|
|
4547
4715
|
pjmedia_stream_info_from_sdp(&stream_info, call->inv->dlg->pool,
|
|
@@ -4607,7 +4775,7 @@ bool restart_media_stream(Call *call, MediaEndpoint *me,
|
|
|
4607
4775
|
return false;
|
|
4608
4776
|
}
|
|
4609
4777
|
|
|
4610
|
-
status = pjmedia_stream_get_port(ae->med_stream, &
|
|
4778
|
+
status = pjmedia_stream_get_port(ae->med_stream, &new_port);
|
|
4611
4779
|
if (status != PJ_SUCCESS) {
|
|
4612
4780
|
make_evt_media_update(evt, sizeof(evt), call->id,
|
|
4613
4781
|
"setup_failed (pjmedia_stream_get_port failed)", "");
|
|
@@ -4615,73 +4783,112 @@ bool restart_media_stream(Call *call, MediaEndpoint *me,
|
|
|
4615
4783
|
return false;
|
|
4616
4784
|
}
|
|
4617
4785
|
|
|
4618
|
-
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
|
|
4622
|
-
dispatch_event(evt);
|
|
4623
|
-
return false;
|
|
4624
|
-
}
|
|
4625
|
-
|
|
4626
|
-
if(!ae->dtmfdet_cbp.port) {
|
|
4627
|
-
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) {
|
|
4628
4790
|
make_evt_media_update(evt, sizeof(evt), call->id,
|
|
4629
|
-
"setup_failed (
|
|
4791
|
+
"setup_failed (create_audio_endpoint_conf failed)", "");
|
|
4630
4792
|
dispatch_event(evt);
|
|
4631
4793
|
return false;
|
|
4632
4794
|
}
|
|
4633
|
-
}
|
|
4634
4795
|
|
|
4635
|
-
|
|
4636
|
-
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);
|
|
4637
4798
|
if (status != PJ_SUCCESS) {
|
|
4638
4799
|
make_evt_media_update(evt, sizeof(evt), call->id,
|
|
4639
|
-
"setup_failed (
|
|
4800
|
+
"setup_failed (pjmedia_conf_add_port failed)", "");
|
|
4640
4801
|
dispatch_event(evt);
|
|
4641
4802
|
return false;
|
|
4642
4803
|
}
|
|
4643
|
-
}
|
|
4644
4804
|
|
|
4645
|
-
|
|
4646
|
-
|
|
4647
|
-
if (status != PJ_SUCCESS) {
|
|
4805
|
+
// we always add dtmfdet to audio endpoints
|
|
4806
|
+
if(!prepare_dtmfdet(call, ae)) {
|
|
4648
4807
|
make_evt_media_update(evt, sizeof(evt), call->id,
|
|
4649
|
-
|
|
4808
|
+
"setup_failed (prepare_dtmfdet failed)", "");
|
|
4650
4809
|
dispatch_event(evt);
|
|
4651
4810
|
return false;
|
|
4652
4811
|
}
|
|
4653
|
-
}
|
|
4654
|
-
|
|
4655
|
-
|
|
4656
|
-
|
|
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);
|
|
4657
4823
|
if (status != PJ_SUCCESS) {
|
|
4658
4824
|
make_evt_media_update(evt, sizeof(evt), call->id,
|
|
4659
|
-
"setup_failed (
|
|
4825
|
+
"setup_failed (create_audio_endpoint_conf failed)", "");
|
|
4660
4826
|
dispatch_event(evt);
|
|
4661
4827
|
return false;
|
|
4662
|
-
|
|
4663
4828
|
}
|
|
4664
|
-
}
|
|
4665
4829
|
|
|
4666
|
-
|
|
4667
|
-
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);
|
|
4668
4832
|
if (status != PJ_SUCCESS) {
|
|
4669
4833
|
make_evt_media_update(evt, sizeof(evt), call->id,
|
|
4670
|
-
"setup_failed (
|
|
4834
|
+
"setup_failed (pjmedia_conf_add_port failed)", "");
|
|
4671
4835
|
dispatch_event(evt);
|
|
4672
4836
|
return false;
|
|
4837
|
+
}
|
|
4673
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;
|
|
4674
4845
|
}
|
|
4675
4846
|
|
|
4676
|
-
|
|
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);
|
|
4677
4855
|
if (status != PJ_SUCCESS) {
|
|
4678
4856
|
make_evt_media_update(evt, sizeof(evt), call->id,
|
|
4679
|
-
"setup_failed (
|
|
4857
|
+
"setup_failed (pjmedia_conf_add_port failed)", "");
|
|
4680
4858
|
dispatch_event(evt);
|
|
4681
4859
|
return false;
|
|
4682
4860
|
}
|
|
4683
|
-
}
|
|
4684
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
|
+
|
|
4685
4892
|
return true;
|
|
4686
4893
|
}
|
|
4687
4894
|
|
|
@@ -4868,8 +5075,6 @@ static void on_state_changed(pjsip_inv_session *inv, pjsip_event *e) {
|
|
|
4868
5075
|
}
|
|
4869
5076
|
}
|
|
4870
5077
|
|
|
4871
|
-
release_call_conf(call);
|
|
4872
|
-
|
|
4873
5078
|
long val;
|
|
4874
5079
|
if (!g_call_ids.remove(call_id, val)) {
|
|
4875
5080
|
addon_log(L_DBG, "g_call_ids.remove failed\n");
|
|
@@ -4889,6 +5094,7 @@ static void on_state_changed(pjsip_inv_session *inv, pjsip_event *e) {
|
|
|
4889
5094
|
sip_msg = e->body.rx_msg.rdata->msg_info.msg_buf;
|
|
4890
5095
|
}
|
|
4891
5096
|
|
|
5097
|
+
printf("call_id=%li sip_msg_len=%i sip_msg=%p\n", call_id, sip_msg_len, sip_msg);
|
|
4892
5098
|
make_evt_call_ended(evt, sizeof(evt), call_id, sip_msg_len, sip_msg);
|
|
4893
5099
|
dispatch_event(evt);
|
|
4894
5100
|
}
|
|
@@ -5259,13 +5465,6 @@ static pj_bool_t on_rx_request(pjsip_rx_data *rdata) {
|
|
|
5259
5465
|
return PJ_TRUE;
|
|
5260
5466
|
}
|
|
5261
5467
|
|
|
5262
|
-
status = setup_call_conf(call);
|
|
5263
|
-
if (status != PJ_SUCCESS) {
|
|
5264
|
-
printf("setup_call_conf failed\n");
|
|
5265
|
-
pjsip_endpt_respond_stateless(g_sip_endpt, rdata, 500, &reason, NULL, NULL);
|
|
5266
|
-
return PJ_TRUE;
|
|
5267
|
-
}
|
|
5268
|
-
|
|
5269
5468
|
// TODO: check if this is really necessary as we are calling
|
|
5270
5469
|
// pjsip_dlg_add_usage subsequently
|
|
5271
5470
|
inv->dlg->mod_data[mod_tester.id] = call;
|
|
@@ -6453,10 +6652,10 @@ bool process_media(Call *call, pjsip_dialog *dlg, Document &document, bool answe
|
|
|
6453
6652
|
return true;
|
|
6454
6653
|
}
|
|
6455
6654
|
|
|
6456
|
-
bool is_media_active(Call *
|
|
6655
|
+
bool is_media_active(Call *call, MediaEndpoint *me) {
|
|
6457
6656
|
// check if media from call->media_neg is on call->media
|
|
6458
|
-
for (int i = 0; i <
|
|
6459
|
-
if (me ==
|
|
6657
|
+
for (int i = 0; i < call->media_count; ++i) {
|
|
6658
|
+
if (me == call->media[i])
|
|
6460
6659
|
return true;
|
|
6461
6660
|
}
|
|
6462
6661
|
return false;
|
|
@@ -6464,18 +6663,14 @@ bool is_media_active(Call *c, MediaEndpoint *me) {
|
|
|
6464
6663
|
|
|
6465
6664
|
void close_media_endpoint(Call *call, MediaEndpoint *me) {
|
|
6466
6665
|
printf("close_media_endpoint %p\n", (void*)me);
|
|
6666
|
+
|
|
6667
|
+
pj_status_t status;
|
|
6668
|
+
|
|
6467
6669
|
if(!me) return;
|
|
6468
6670
|
|
|
6469
6671
|
if (ENDPOINT_TYPE_AUDIO == me->type) {
|
|
6470
6672
|
AudioEndpoint *ae = (AudioEndpoint *)me->endpoint.audio;
|
|
6471
|
-
|
|
6472
|
-
audio_endpoint_remove_port(call, &ae->stream_cbp);
|
|
6473
|
-
audio_endpoint_remove_port(call, &ae->wav_player_cbp);
|
|
6474
|
-
audio_endpoint_remove_port(call, &ae->wav_writer_cbp);
|
|
6475
|
-
audio_endpoint_remove_port(call, &ae->tonegen_cbp);
|
|
6476
|
-
audio_endpoint_remove_port(call, &ae->dtmfdet_cbp);
|
|
6477
|
-
audio_endpoint_remove_port(call, &ae->fax_cbp);
|
|
6478
|
-
|
|
6673
|
+
close_audio_endpoint_ports_and_conf(call, ae);
|
|
6479
6674
|
close_media_transport(ae->med_transport);
|
|
6480
6675
|
ae->med_transport = NULL;
|
|
6481
6676
|
} else if (ENDPOINT_TYPE_MRCP == me->type) {
|
|
@@ -6499,17 +6694,17 @@ void close_media_endpoint(Call *call, MediaEndpoint *me) {
|
|
|
6499
6694
|
me->port = 0;
|
|
6500
6695
|
}
|
|
6501
6696
|
|
|
6502
|
-
void close_media(Call *
|
|
6503
|
-
printf("close_media call_id=%
|
|
6504
|
-
for (int i = 0; i <
|
|
6505
|
-
MediaEndpoint *me =
|
|
6506
|
-
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);
|
|
6507
6702
|
}
|
|
6508
|
-
|
|
6703
|
+
call->media_count = 0;
|
|
6509
6704
|
}
|
|
6510
6705
|
|
|
6511
|
-
bool prepare_tonegen(Call *
|
|
6512
|
-
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);
|
|
6513
6708
|
pj_status_t status;
|
|
6514
6709
|
|
|
6515
6710
|
if(ae->tonegen_cbp.port) {
|
|
@@ -6518,7 +6713,7 @@ bool prepare_tonegen(Call *c, AudioEndpoint *ae) {
|
|
|
6518
6713
|
}
|
|
6519
6714
|
|
|
6520
6715
|
status = pjmedia_tonegen_create(
|
|
6521
|
-
|
|
6716
|
+
call->inv->pool, PJMEDIA_PIA_SRATE(&ae->stream_cbp.port->info),
|
|
6522
6717
|
PJMEDIA_PIA_CCNT(&ae->stream_cbp.port->info),
|
|
6523
6718
|
PJMEDIA_PIA_SPF(&ae->stream_cbp.port->info),
|
|
6524
6719
|
PJMEDIA_PIA_BITS(&ae->stream_cbp.port->info), 0, &ae->tonegen_cbp.port);
|
|
@@ -6527,22 +6722,16 @@ bool prepare_tonegen(Call *c, AudioEndpoint *ae) {
|
|
|
6527
6722
|
return false;
|
|
6528
6723
|
}
|
|
6529
6724
|
|
|
6530
|
-
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);
|
|
6531
6726
|
if (status != PJ_SUCCESS) {
|
|
6532
6727
|
set_error("pjmedia_conf_add_port failed");
|
|
6533
6728
|
return false;
|
|
6534
6729
|
}
|
|
6535
6730
|
|
|
6536
|
-
|
|
6537
|
-
if (status != PJ_SUCCESS) {
|
|
6538
|
-
set_error("pjmedia_conf_connect_port failed");
|
|
6539
|
-
return false;
|
|
6540
|
-
}
|
|
6541
|
-
|
|
6542
|
-
return true;
|
|
6731
|
+
return connect_feature_port_to_stream_port(call, ae, &ae->tonegen_cbp, CONNECTION_MODE_SOURCE);
|
|
6543
6732
|
}
|
|
6544
6733
|
|
|
6545
|
-
bool prepare_wav_player(Call *
|
|
6734
|
+
bool prepare_wav_player(Call *call, AudioEndpoint *ae, const char *file, unsigned flags, bool end_of_file_event) {
|
|
6546
6735
|
pj_status_t status;
|
|
6547
6736
|
|
|
6548
6737
|
unsigned wav_ptime;
|
|
@@ -6550,10 +6739,10 @@ bool prepare_wav_player(Call *c, AudioEndpoint *ae, const char *file) {
|
|
|
6550
6739
|
PJMEDIA_PIA_SRATE(&ae->stream_cbp.port->info);
|
|
6551
6740
|
|
|
6552
6741
|
status = pjmedia_wav_player_port_create(
|
|
6553
|
-
|
|
6742
|
+
call->inv->pool,
|
|
6554
6743
|
file,
|
|
6555
6744
|
wav_ptime,
|
|
6556
|
-
|
|
6745
|
+
flags,
|
|
6557
6746
|
-1, /* buf size */
|
|
6558
6747
|
&ae->wav_player_cbp.port
|
|
6559
6748
|
);
|
|
@@ -6563,26 +6752,28 @@ bool prepare_wav_player(Call *c, AudioEndpoint *ae, const char *file) {
|
|
|
6563
6752
|
return false;
|
|
6564
6753
|
}
|
|
6565
6754
|
|
|
6566
|
-
|
|
6567
|
-
|
|
6568
|
-
|
|
6569
|
-
|
|
6755
|
+
if (end_of_file_event) {
|
|
6756
|
+
status = pjmedia_wav_player_set_eof_cb2(ae->wav_player_cbp.port, (void*)call, on_end_of_file);
|
|
6757
|
+
if (status != PJ_SUCCESS) {
|
|
6758
|
+
set_error("pjmedia_wav_player_set_eof_cb2 failed");
|
|
6759
|
+
return false;
|
|
6760
|
+
}
|
|
6570
6761
|
}
|
|
6571
6762
|
|
|
6572
|
-
status =
|
|
6763
|
+
status = pjmedia_conf_add_port(ae->conf, call->inv->pool, ae->wav_player_cbp.port, NULL, &ae->wav_player_cbp.slot);
|
|
6573
6764
|
if (status != PJ_SUCCESS) {
|
|
6574
|
-
set_error("
|
|
6765
|
+
set_error("pjmedia_conf_add_port failed");
|
|
6575
6766
|
return false;
|
|
6576
6767
|
}
|
|
6577
6768
|
|
|
6578
|
-
return
|
|
6769
|
+
return connect_feature_port_to_stream_port(call, ae, &ae->wav_player_cbp, CONNECTION_MODE_SOURCE);
|
|
6579
6770
|
}
|
|
6580
6771
|
|
|
6581
|
-
bool prepare_wav_writer(Call *
|
|
6772
|
+
bool prepare_wav_writer(Call *call, AudioEndpoint *ae, const char *file) {
|
|
6582
6773
|
pj_status_t status;
|
|
6583
6774
|
|
|
6584
6775
|
status = pjmedia_wav_writer_port_create(
|
|
6585
|
-
|
|
6776
|
+
call->inv->pool, file, PJMEDIA_PIA_SRATE(&ae->stream_cbp.port->info),
|
|
6586
6777
|
PJMEDIA_PIA_CCNT(&ae->stream_cbp.port->info), PJMEDIA_PIA_SPF(&ae->stream_cbp.port->info),
|
|
6587
6778
|
PJMEDIA_PIA_BITS(&ae->stream_cbp.port->info), PJMEDIA_FILE_WRITE_PCM, 0,
|
|
6588
6779
|
(pjmedia_port **)&ae->wav_writer_cbp.port);
|
|
@@ -6591,122 +6782,131 @@ bool prepare_wav_writer(Call *c, AudioEndpoint *ae, const char *file) {
|
|
|
6591
6782
|
return false;
|
|
6592
6783
|
}
|
|
6593
6784
|
|
|
6594
|
-
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);
|
|
6595
6786
|
if (status != PJ_SUCCESS) {
|
|
6596
6787
|
set_error("pjmedia_conf_add_port failed");
|
|
6597
6788
|
return false;
|
|
6598
6789
|
}
|
|
6599
6790
|
|
|
6600
|
-
|
|
6601
|
-
if (status != PJ_SUCCESS) {
|
|
6602
|
-
set_error("pjmedia_conf_connect_port failed");
|
|
6603
|
-
return false;
|
|
6604
|
-
}
|
|
6605
|
-
|
|
6606
|
-
return true;
|
|
6791
|
+
return connect_feature_port_to_stream_port(call, ae, &ae->wav_writer_cbp, CONNECTION_MODE_SINK);
|
|
6607
6792
|
}
|
|
6608
6793
|
|
|
6609
|
-
bool prepare_dtmfdet(Call *
|
|
6794
|
+
bool prepare_dtmfdet(Call *call, AudioEndpoint *ae) {
|
|
6610
6795
|
pj_status_t status;
|
|
6611
6796
|
status = pjmedia_dtmfdet_create(
|
|
6612
|
-
|
|
6797
|
+
call->inv->pool,
|
|
6613
6798
|
PJMEDIA_PIA_SRATE(&ae->stream_cbp.port->info),
|
|
6614
|
-
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),
|
|
6615
6801
|
PJMEDIA_PIA_BITS(&ae->stream_cbp.port->info),
|
|
6616
|
-
on_inband_dtmf,
|
|
6802
|
+
on_inband_dtmf, call, &ae->dtmfdet_cbp.port);
|
|
6617
6803
|
if (status != PJ_SUCCESS) {
|
|
6618
6804
|
set_error("pjmedia_dtmfdet_create failed");
|
|
6619
6805
|
return false;
|
|
6620
6806
|
}
|
|
6621
6807
|
|
|
6622
|
-
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);
|
|
6623
6809
|
if (status != PJ_SUCCESS) {
|
|
6624
6810
|
set_error("pjmedia_conf_add_port failed");
|
|
6625
6811
|
return false;
|
|
6626
6812
|
}
|
|
6627
6813
|
|
|
6628
|
-
|
|
6629
|
-
if (status != PJ_SUCCESS) {
|
|
6630
|
-
set_error("pjmedia_conf_connect_port failed");
|
|
6631
|
-
return false;
|
|
6632
|
-
}
|
|
6633
|
-
|
|
6634
|
-
return true;
|
|
6814
|
+
return connect_feature_port_to_stream_port(call, ae, &ae->dtmfdet_cbp, CONNECTION_MODE_SINK);
|
|
6635
6815
|
}
|
|
6636
6816
|
|
|
6637
|
-
bool prepare_fax(Call *
|
|
6817
|
+
bool prepare_fax(Call *call, AudioEndpoint *ae, bool is_sender, const char *file,
|
|
6638
6818
|
unsigned flags) {
|
|
6639
6819
|
pj_status_t status;
|
|
6640
6820
|
|
|
6641
6821
|
status = pjmedia_fax_port_create(
|
|
6642
|
-
|
|
6822
|
+
call->inv->pool,
|
|
6643
6823
|
PJMEDIA_PIA_SRATE(&ae->stream_cbp.port->info),
|
|
6644
6824
|
PJMEDIA_PIA_CCNT(&ae->stream_cbp.port->info),
|
|
6645
6825
|
PJMEDIA_PIA_SPF(&ae->stream_cbp.port->info),
|
|
6646
6826
|
PJMEDIA_PIA_BITS(&ae->stream_cbp.port->info),
|
|
6647
|
-
on_fax_result,
|
|
6827
|
+
on_fax_result, call, is_sender, file,
|
|
6648
6828
|
flags, &ae->fax_cbp.port);
|
|
6649
6829
|
if (status != PJ_SUCCESS) {
|
|
6650
6830
|
set_error("pjmedia_fax_port_create failed");
|
|
6651
6831
|
return false;
|
|
6652
6832
|
}
|
|
6653
6833
|
|
|
6654
|
-
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);
|
|
6655
6835
|
if (status != PJ_SUCCESS) {
|
|
6656
6836
|
set_error("pjmedia_conf_add_port failed");
|
|
6657
6837
|
return false;
|
|
6658
6838
|
}
|
|
6659
6839
|
|
|
6660
|
-
|
|
6840
|
+
return connect_feature_port_to_stream_port(call, ae, &ae->fax_cbp, CONNECTION_MODE_SOURCE_AND_SINK);
|
|
6841
|
+
}
|
|
6842
|
+
|
|
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);
|
|
6845
|
+
pj_status_t status;
|
|
6846
|
+
|
|
6847
|
+
if(ae->flite_cbp.port) {
|
|
6848
|
+
printf("already prepared\n");
|
|
6849
|
+
return true;
|
|
6850
|
+
}
|
|
6851
|
+
|
|
6852
|
+
status = pjmedia_flite_port_create(
|
|
6853
|
+
call->inv->pool, PJMEDIA_PIA_SRATE(&ae->stream_cbp.port->info),
|
|
6854
|
+
PJMEDIA_PIA_CCNT(&ae->stream_cbp.port->info),
|
|
6855
|
+
PJMEDIA_PIA_SPF(&ae->stream_cbp.port->info),
|
|
6856
|
+
PJMEDIA_PIA_BITS(&ae->stream_cbp.port->info), voice, &ae->flite_cbp.port);
|
|
6661
6857
|
if (status != PJ_SUCCESS) {
|
|
6662
|
-
set_error("
|
|
6858
|
+
set_error("pjmedia_flite_port_create failed");
|
|
6663
6859
|
return false;
|
|
6664
6860
|
}
|
|
6665
6861
|
|
|
6666
|
-
|
|
6862
|
+
if (end_of_speech_event) {
|
|
6863
|
+
status = pjmedia_flite_port_set_eof_cb(ae->flite_cbp.port, (void*)call, on_end_of_speech);
|
|
6864
|
+
if (status != PJ_SUCCESS) {
|
|
6865
|
+
set_error("pjmedia_flite_port_set_eof_cb failed");
|
|
6866
|
+
return false;
|
|
6867
|
+
}
|
|
6868
|
+
}
|
|
6869
|
+
|
|
6870
|
+
status = pjmedia_conf_add_port(ae->conf, call->inv->pool, ae->flite_cbp.port, NULL, &ae->flite_cbp.slot);
|
|
6667
6871
|
if (status != PJ_SUCCESS) {
|
|
6668
|
-
set_error("
|
|
6872
|
+
set_error("pjmedia_conf_add_port failed");
|
|
6669
6873
|
return false;
|
|
6670
6874
|
}
|
|
6671
6875
|
|
|
6672
|
-
return
|
|
6876
|
+
return connect_feature_port_to_stream_port(call, ae, &ae->flite_cbp, CONNECTION_MODE_SOURCE);
|
|
6673
6877
|
}
|
|
6674
6878
|
|
|
6675
|
-
bool
|
|
6676
|
-
printf("
|
|
6879
|
+
bool prepare_pocketsphinx(Call *call, AudioEndpoint *ae) {
|
|
6880
|
+
printf("prepare_pocketsphinx call.id=%i\n", call->id);
|
|
6677
6881
|
pj_status_t status;
|
|
6678
6882
|
|
|
6679
|
-
if(ae->
|
|
6883
|
+
if(ae->pocketsphinx_cbp.port) {
|
|
6680
6884
|
printf("already prepared\n");
|
|
6681
6885
|
return true;
|
|
6682
6886
|
}
|
|
6683
6887
|
|
|
6684
|
-
status =
|
|
6685
|
-
|
|
6888
|
+
status = pjmedia_pocketsphinx_port_create(
|
|
6889
|
+
call->inv->pool, PJMEDIA_PIA_SRATE(&ae->stream_cbp.port->info),
|
|
6686
6890
|
PJMEDIA_PIA_CCNT(&ae->stream_cbp.port->info),
|
|
6687
6891
|
PJMEDIA_PIA_SPF(&ae->stream_cbp.port->info),
|
|
6688
|
-
PJMEDIA_PIA_BITS(&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);
|
|
6689
6896
|
if (status != PJ_SUCCESS) {
|
|
6690
|
-
set_error("
|
|
6897
|
+
set_error("pjmedia_pocketsphinx_port_create failed");
|
|
6691
6898
|
return false;
|
|
6692
6899
|
}
|
|
6693
6900
|
|
|
6694
|
-
status = pjmedia_conf_add_port(
|
|
6901
|
+
status = pjmedia_conf_add_port(ae->conf, call->inv->pool, ae->pocketsphinx_cbp.port, NULL, &ae->pocketsphinx_cbp.slot);
|
|
6695
6902
|
if (status != PJ_SUCCESS) {
|
|
6696
6903
|
set_error("pjmedia_conf_add_port failed");
|
|
6697
6904
|
return false;
|
|
6698
6905
|
}
|
|
6699
6906
|
|
|
6700
|
-
|
|
6701
|
-
if (status != PJ_SUCCESS) {
|
|
6702
|
-
set_error("pjmedia_conf_connect_port failed");
|
|
6703
|
-
return false;
|
|
6704
|
-
}
|
|
6705
|
-
|
|
6706
|
-
return true;
|
|
6907
|
+
return connect_feature_port_to_stream_port(call, ae, &ae->pocketsphinx_cbp, CONNECTION_MODE_SINK);
|
|
6707
6908
|
}
|
|
6708
6909
|
|
|
6709
|
-
|
|
6710
6910
|
void on_rx_notify(pjsip_evsub *sub, pjsip_rx_data *rdata, int *p_st_code,
|
|
6711
6911
|
pj_str_t **p_st_text, pjsip_hdr *res_hdr,
|
|
6712
6912
|
pjsip_msg_body **p_body) {
|
|
@@ -8012,7 +8212,7 @@ int pjw_call_send_tcp_msg(long call_id, const char *json) {
|
|
|
8012
8212
|
MediaEndpoint *me;
|
|
8013
8213
|
int res;
|
|
8014
8214
|
|
|
8015
|
-
|
|
8215
|
+
int media_id = -1;
|
|
8016
8216
|
|
|
8017
8217
|
char buffer[MAX_JSON_INPUT];
|
|
8018
8218
|
|
|
@@ -8036,7 +8236,7 @@ int pjw_call_send_tcp_msg(long call_id, const char *json) {
|
|
|
8036
8236
|
}
|
|
8037
8237
|
size = strlen(msg);
|
|
8038
8238
|
|
|
8039
|
-
res =
|
|
8239
|
+
res = json_get_int_param(document, "media_id", true, &media_id);
|
|
8040
8240
|
if (res <= 0) {
|
|
8041
8241
|
goto out;
|
|
8042
8242
|
}
|
|
@@ -8050,7 +8250,7 @@ int pjw_call_send_tcp_msg(long call_id, const char *json) {
|
|
|
8050
8250
|
} else {
|
|
8051
8251
|
// Send msg to specified media_id
|
|
8052
8252
|
|
|
8053
|
-
if (
|
|
8253
|
+
if (media_id >= call->media_count) {
|
|
8054
8254
|
set_error("invalid media_id");
|
|
8055
8255
|
goto out;
|
|
8056
8256
|
}
|
|
@@ -8093,8 +8293,8 @@ static int g_now;
|
|
|
8093
8293
|
|
|
8094
8294
|
void check_digit_buffer(Call *call, int mode) {
|
|
8095
8295
|
// addon_log(L_DBG, "check_digit_buffer g_now=%i for call_id=%i and mode=%i
|
|
8096
|
-
// timestamp=%i len=%i\n", g_now,
|
|
8097
|
-
//
|
|
8296
|
+
// timestamp=%i len=%i\n", g_now, call->id, mode, call->last_digit_timestamp[mode],
|
|
8297
|
+
// call->DigitBufferLength[mode]);
|
|
8098
8298
|
char evt[1024];
|
|
8099
8299
|
|
|
8100
8300
|
for (int i = 0; i < call->media_count; i++) {
|
|
@@ -8118,10 +8318,10 @@ void check_digit_buffer(Call *call, int mode) {
|
|
|
8118
8318
|
}
|
|
8119
8319
|
|
|
8120
8320
|
void check_digit_buffers(long id, long val) {
|
|
8121
|
-
Call *
|
|
8321
|
+
Call *call = (Call *)val;
|
|
8122
8322
|
|
|
8123
|
-
check_digit_buffer(
|
|
8124
|
-
check_digit_buffer(
|
|
8323
|
+
check_digit_buffer(call, DTMF_MODE_RFC2833);
|
|
8324
|
+
check_digit_buffer(call, DTMF_MODE_INBAND);
|
|
8125
8325
|
}
|
|
8126
8326
|
|
|
8127
8327
|
static int digit_buffer_thread(void *arg) {
|