Browse Source

MT#59038 support DTMF VSC to control recording

Change-Id: I57c5bec312419eff90efb06c5b1cee998f1f9466
pull/1802/head
Richard Fuchs 2 years ago
parent
commit
50848552c6
7 changed files with 215 additions and 0 deletions
  1. +14
    -0
      daemon/call.c
  2. +39
    -0
      daemon/call_interfaces.c
  3. +125
    -0
      daemon/dtmf.c
  4. +15
    -0
      daemon/main.c
  5. +8
    -0
      include/call_interfaces.h
  6. +8
    -0
      include/dtmf.h
  7. +6
    -0
      include/main.h

+ 14
- 0
daemon/call.c View File

@ -2597,6 +2597,20 @@ static void __call_monologue_init_from_flags(struct call_monologue *ml, sdp_ng_f
t_hash_table_replace(call->labels, &ml->label, ml);
}
if (flags->recording_vsc) {
#define SET_VSC(x,t) \
if (flags->vsc_ ## x ## _rec.len) \
dtmf_trigger_set(ml, DTMF_TRIGGER_ ## t ## _REC, &flags->vsc_ ## x ## _rec, false); \
else \
dtmf_trigger_set(ml, DTMF_TRIGGER_ ## t ## _REC, &rtpe_config.vsc_ ## x ## _rec, false);
SET_VSC(start, START)
SET_VSC(stop, STOP)
SET_VSC(pause, PAUSE)
SET_VSC(start_stop, START_STOP)
SET_VSC(pause_resume, PAUSE_RESUME)
SET_VSC(start_pause_resume, START_PAUSE_RESUME)
#undef SET_VSC
}
}
__attribute__((nonnull(2, 3)))


+ 39
- 0
daemon/call_interfaces.c View File

@ -1125,6 +1125,9 @@ static void call_ng_flags_flags(sdp_ng_flags *out, str *s, helper_arg dummy) {
case CSH_LOOKUP("record-call"):
out->record_call = 1;
break;
case CSH_LOOKUP("recording-vsc"):
out->recording_vsc = 1;
break;
case CSH_LOOKUP("reorder-codecs"):
ilog(LOG_INFO, "Ignoring obsolete flag `reorder-codecs`");
break;
@ -1883,6 +1886,42 @@ static void call_ng_main_flags(sdp_ng_flags *out, str *key, bencode_item_t *valu
case CSH_LOOKUP("volume"):
out->volume = bencode_get_integer_str(value, out->volume);
break;
case CSH_LOOKUP("vsc-pause-rec"):
case CSH_LOOKUP("VSC-pause-rec"):
case CSH_LOOKUP("vsc-pause-recording"):
case CSH_LOOKUP("VSC-pause-recording"):
out->vsc_pause_rec = s;
break;
case CSH_LOOKUP("vsc-pause-resume-rec"):
case CSH_LOOKUP("VSC-pause-resume-rec"):
case CSH_LOOKUP("vsc-pause-resume-recording"):
case CSH_LOOKUP("VSC-pause-resume-recording"):
out->vsc_pause_resume_rec = s;
break;
case CSH_LOOKUP("vsc-start-pause-resume-rec"):
case CSH_LOOKUP("VSC-start-pause-resume-rec"):
case CSH_LOOKUP("vsc-start-pause-resume-recording"):
case CSH_LOOKUP("VSC-start-pause-resume-recording"):
out->vsc_start_pause_resume_rec = s;
break;
case CSH_LOOKUP("vsc-start-rec"):
case CSH_LOOKUP("VSC-start-rec"):
case CSH_LOOKUP("vsc-start-recording"):
case CSH_LOOKUP("VSC-start-recording"):
out->vsc_start_rec = s;
break;
case CSH_LOOKUP("vsc-start-stop-rec"):
case CSH_LOOKUP("VSC-start-stop-rec"):
case CSH_LOOKUP("vsc-start-stop-recording"):
case CSH_LOOKUP("VSC-start-stop-recording"):
out->vsc_start_stop_rec = s;
break;
case CSH_LOOKUP("vsc-stop-rec"):
case CSH_LOOKUP("VSC-stop-rec"):
case CSH_LOOKUP("vsc-stop-recording"):
case CSH_LOOKUP("VSC-stop-recording"):
out->vsc_stop_rec = s;
break;
case CSH_LOOKUP("xmlrpc-callback"):
case CSH_LOOKUP("XMLRPC-callback"):
if (sockaddr_parse_any_str(&out->xmlrpc_callback, &s))


+ 125
- 0
daemon/dtmf.c View File

@ -19,6 +19,12 @@ static socket_t dtmf_log_sock;
static void dtmf_trigger_block_action(struct call_media *, struct call_monologue *);
static void dtmf_trigger_block_digit(struct call_media *, struct call_monologue *);
static void dtmf_trigger_unblock_action(struct call_media *, struct call_monologue *);
static void dtmf_trigger_start_rec(struct call_media *, struct call_monologue *);
static void dtmf_trigger_stop_rec(struct call_media *, struct call_monologue *);
static void dtmf_trigger_start_stop_rec(struct call_media *, struct call_monologue *);
static void dtmf_trigger_pause_rec(struct call_media *, struct call_monologue *);
static void dtmf_trigger_pause_resume_rec(struct call_media *, struct call_monologue *);
static void dtmf_trigger_start_pause_resume_rec(struct call_media *, struct call_monologue *);
struct dtmf_trigger_action dtmf_trigger_actions[__NUM_DTMF_TRIGGERS] = {
[DTMF_TRIGGER_BLOCK] = {
@ -30,6 +36,41 @@ struct dtmf_trigger_action dtmf_trigger_actions[__NUM_DTMF_TRIGGERS] = {
.matched = dtmf_trigger_unblock_action,
.repeatable = false,
},
[DTMF_TRIGGER_START_REC] = {
.matched = dtmf_trigger_start_rec,
.repeatable = true,
},
[DTMF_TRIGGER_STOP_REC] = {
.matched = dtmf_trigger_stop_rec,
.repeatable = true,
},
[DTMF_TRIGGER_START_STOP_REC] = {
.matched = dtmf_trigger_start_stop_rec,
.repeatable = true,
},
[DTMF_TRIGGER_PAUSE_REC] = {
.matched = dtmf_trigger_pause_rec,
.repeatable = true,
},
[DTMF_TRIGGER_PAUSE_RESUME_REC] = {
.matched = dtmf_trigger_pause_resume_rec,
.repeatable = true,
},
[DTMF_TRIGGER_START_PAUSE_RESUME_REC] = {
.matched = dtmf_trigger_start_pause_resume_rec,
.repeatable = true,
},
};
const char *dtmf_trigger_types[__NUM_DTMF_TRIGGERS] = {
[DTMF_TRIGGER_BLOCK] = "block DTMF",
[DTMF_TRIGGER_UNBLOCK] = "unblock DTMF",
[DTMF_TRIGGER_START_REC] = "start recording",
[DTMF_TRIGGER_STOP_REC] = "stop recording",
[DTMF_TRIGGER_START_STOP_REC] = "start/stop recording",
[DTMF_TRIGGER_PAUSE_REC] = "pause recording",
[DTMF_TRIGGER_PAUSE_RESUME_REC] = "pause/resume recording",
[DTMF_TRIGGER_START_PAUSE_RESUME_REC] = "start/pause/resume recording",
};
@ -259,6 +300,10 @@ void dtmf_trigger_set(struct call_monologue *ml, enum dtmf_trigger_type trigger_
// Replace existing trigger below
}
ilog(LOG_DEBUG, "Setting DTMF trigger '%s' (at idx %u) to '" STR_FORMAT "'",
dtmf_trigger_types[trigger_type],
(unsigned int) (state - ml->dtmf_trigger_state), STR_FMT(s));
call_str_cpy(ml->call, &state->trigger, s);
state->matched = 0;
state->inactive = inactive;
@ -365,6 +410,9 @@ static bool dtmf_check_1_trigger(struct call_media *media, struct call_monologue
// trigger is finished
state->matched = 0; // reset
ilog(LOG_INFO, "DTMF VSC '%s' ('" STR_FORMAT "') triggered",
dtmf_trigger_types[state->type], STR_FMT(&state->trigger));
action->matched(media, ml);
if (!action->repeatable)
@ -835,3 +883,80 @@ bool is_dtmf_replace_mode(enum block_dtmf_mode mode) {
return true;
return false;
}
static void dtmf_trigger_do_start_rec(call_t *c, codec_timer_callback_arg_t a) {
rwlock_lock_w(&c->master_lock);
recording_start(c);
rwlock_unlock_w(&c->master_lock);
}
// dtmf_lock must be held
static void dtmf_trigger_start_rec(struct call_media *media, struct call_monologue *ml) {
codec_timer_callback(ml->call, dtmf_trigger_do_start_rec, ml, 0);
}
static void dtmf_trigger_do_stop_rec(call_t *c, codec_timer_callback_arg_t a) {
rwlock_lock_w(&c->master_lock);
recording_stop(c);
rwlock_unlock_w(&c->master_lock);
}
// dtmf_lock must be held
static void dtmf_trigger_stop_rec(struct call_media *media, struct call_monologue *ml) {
codec_timer_callback(ml->call, dtmf_trigger_do_stop_rec, ml, 0);
}
static void dtmf_trigger_do_start_stop_rec(call_t *c, codec_timer_callback_arg_t a) {
rwlock_lock_w(&c->master_lock);
if (c->recording)
recording_stop(c);
else
recording_start(c);
rwlock_unlock_w(&c->master_lock);
}
// dtmf_lock must be held
static void dtmf_trigger_start_stop_rec(struct call_media *media, struct call_monologue *ml) {
codec_timer_callback(ml->call, dtmf_trigger_do_start_stop_rec, ml, 0);
}
static void dtmf_trigger_do_pause_rec(call_t *c, codec_timer_callback_arg_t a) {
rwlock_lock_w(&c->master_lock);
recording_pause(c);
rwlock_unlock_w(&c->master_lock);
}
// dtmf_lock must be held
static void dtmf_trigger_pause_rec(struct call_media *media, struct call_monologue *ml) {
codec_timer_callback(ml->call, dtmf_trigger_do_pause_rec, ml, 0);
}
static void dtmf_trigger_do_pause_resume_rec(call_t *c, codec_timer_callback_arg_t a) {
rwlock_lock_w(&c->master_lock);
if (!c->recording)
return;
if (CALL_SET(c, RECORDING_ON))
recording_pause(c);
else
recording_start(c);
rwlock_unlock_w(&c->master_lock);
}
// dtmf_lock must be held
static void dtmf_trigger_pause_resume_rec(struct call_media *media, struct call_monologue *ml) {
codec_timer_callback(ml->call, dtmf_trigger_do_pause_resume_rec, ml, 0);
}
static void dtmf_trigger_do_start_pause_resume_rec(call_t *c, codec_timer_callback_arg_t a) {
rwlock_lock_w(&c->master_lock);
if (CALL_SET(c, RECORDING_ON))
recording_pause(c);
else
recording_start(c);
rwlock_unlock_w(&c->master_lock);
}
// dtmf_lock must be held
static void dtmf_trigger_start_pause_resume_rec(struct call_media *media, struct call_monologue *ml) {
codec_timer_callback(ml->call, dtmf_trigger_do_start_pause_resume_rec, ml, 0);
}

+ 15
- 0
daemon/main.c View File

@ -648,6 +648,12 @@ static void options(int *argc, char ***argv) {
{ "janus-secret", 0,0, G_OPTION_ARG_STRING, &rtpe_config.janus_secret,"Admin secret for Janus protocol","STRING"},
{ "rtcp-interval", 0,0, G_OPTION_ARG_INT, &rtpe_config.rtcp_interval,"Delay in milliseconds between RTCP packets when generate-rtcp flag is on, where random dispersion < 1 sec is added on top","INT"},
{ "max-recv-iters", 0, 0, G_OPTION_ARG_INT, &rtpe_config.max_recv_iters, "Maximun continuous reading cycles in UDP poller loop.", "INT"},
{ "vsc-start-rec",0,0, G_OPTION_ARG_STRING, &rtpe_config.vsc_start_rec.s,"DTMF VSC to start recording.", "STRING"},
{ "vsc-stop-rec",0,0, G_OPTION_ARG_STRING, &rtpe_config.vsc_stop_rec.s,"DTMF VSC to stop recording.", "STRING"},
{ "vsc-start-stop-rec",0,0,G_OPTION_ARG_STRING, &rtpe_config.vsc_start_stop_rec.s,"DTMF VSC to start/stop recording.", "STRING"},
{ "vsc-pause-rec",0,0, G_OPTION_ARG_STRING, &rtpe_config.vsc_pause_rec.s,"DTMF VSC to pause recording.", "STRING"},
{ "vsc-pause-resume-rec",0,0,G_OPTION_ARG_STRING,&rtpe_config.vsc_pause_resume_rec.s,"DTMF VSC to pause/resume recording.", "STRING"},
{ "vsc-start-pause-resume-rec",0,0,G_OPTION_ARG_STRING,&rtpe_config.vsc_start_pause_resume_rec.s,"DTMF VSC to start/pause/resume recording.", "STRING"},
{ NULL, }
};
@ -1014,6 +1020,15 @@ static void options(int *argc, char ***argv) {
die("Invalid --control-pmtu option ('%s')", control_pmtu);
}
#define STR_LEN_INIT(x) if (rtpe_config.x.s) rtpe_config.x.len = strlen(rtpe_config.x.s)
STR_LEN_INIT(vsc_start_rec);
STR_LEN_INIT(vsc_stop_rec);
STR_LEN_INIT(vsc_start_stop_rec);
STR_LEN_INIT(vsc_pause_rec);
STR_LEN_INIT(vsc_pause_resume_rec);
STR_LEN_INIT(vsc_start_pause_resume_rec);
#undef STR_LEN_INIT
rwlock_unlock_w(&rtpe_config.config_lock);
}


+ 8
- 0
include/call_interfaces.h View File

@ -118,6 +118,13 @@ struct sdp_ng_flags {
AP_TRANSCODING,
AP_FORCE,
} audio_player:2;
str vsc_start_rec;
str vsc_stop_rec;
str vsc_start_stop_rec;
str vsc_pause_rec;
str vsc_pause_resume_rec;
str vsc_start_pause_resume_rec;
unsigned int asymmetric:1,
protocol_accept:1,
no_redis_update:1,
@ -162,6 +169,7 @@ struct sdp_ng_flags {
discard_recording:1,
exclude_recording:1,
skip_recording_db:1,
recording_vsc:1,
debug:1,
inactive:1,
loop_protect:1,


+ 8
- 0
include/dtmf.h View File

@ -17,10 +17,18 @@ struct call_monologue;
enum dtmf_trigger_type {
DTMF_TRIGGER_BLOCK = 0,
DTMF_TRIGGER_UNBLOCK,
DTMF_TRIGGER_START_REC,
DTMF_TRIGGER_STOP_REC,
DTMF_TRIGGER_START_STOP_REC,
DTMF_TRIGGER_PAUSE_REC,
DTMF_TRIGGER_PAUSE_RESUME_REC,
DTMF_TRIGGER_START_PAUSE_RESUME_REC,
__NUM_DTMF_TRIGGERS,
};
extern const char *dtmf_trigger_types[__NUM_DTMF_TRIGGERS];
struct dtmf_trigger_state {
enum dtmf_trigger_type type; // points to matching action
str trigger; // string to look for


+ 6
- 0
include/main.h View File

@ -187,6 +187,12 @@ struct rtpengine_config {
int cpu_affinity;
char *janus_secret;
int max_recv_iters;
str vsc_start_rec;
str vsc_stop_rec;
str vsc_start_stop_rec;
str vsc_pause_rec;
str vsc_pause_resume_rec;
str vsc_start_pause_resume_rec;
};


Loading…
Cancel
Save