TT#79601 support media/DTMF playback to all parties

Change-Id: I534ba39c800e0b075c1502808a56b887baf3e323
changes/79/39279/3
Richard Fuchs 6 years ago
parent e7c85ce578
commit c1d29a41a7

@ -1571,7 +1571,8 @@ and stopped independently of each other.
Only available if compiled with transcoding support. The message must contain the key `call-id` and one Only available if compiled with transcoding support. The message must contain the key `call-id` and one
of the participant selection keys described under the `block DTMF` message (such as `from-tag`, of the participant selection keys described under the `block DTMF` message (such as `from-tag`,
`address`, or `label`). `address`, or `label`). Alternatively, the `all` flag can be set to play the media to all involved
call parties.
Starts playback of a provided media file to the selected call participant. The format of the media file Starts playback of a provided media file to the selected call participant. The format of the media file
can be anything that is supported by *ffmpeg*, for example a `.wav` or `.mp3` file. It will automatically can be anything that is supported by *ffmpeg*, for example a `.wav` or `.mp3` file. It will automatically
@ -1611,8 +1612,9 @@ The same participant selection keys as for the `play media` message can and must
------------------- -------------------
Instructs *rtpengine* to inject a DTMF tone or event into a running audio stream. A call participant must Instructs *rtpengine* to inject a DTMF tone or event into a running audio stream. A call participant must
be selected in the same way as described under the `block DTMF` message above. The selected call participant be selected in the same way as described under the `play media` message above (including the possibility
is the one generating the DTMF event, not the one receiving it. of using the `all` flag). The selected call participant is the one generating the DTMF event, not the
one receiving it.
The dictionary key `code` must be present in the message, indicating the DTMF event to be generated. It can The dictionary key `code` must be present in the message, indicating the DTMF event to be generated. It can
be either an integer with values 0-15, or a string containing a single character be either an integer with values 0-15, or a string containing a single character

@ -1603,6 +1603,9 @@ static const char *media_block_match(struct call **call, struct call_monologue *
return "Unknown call-id"; return "Unknown call-id";
// directional? // directional?
if (flags->all) // explicitly non-directional, so skip the rest
return NULL;
if (flags->label.s) { if (flags->label.s) {
*monologue = g_hash_table_lookup((*call)->labels, &flags->label); *monologue = g_hash_table_lookup((*call)->labels, &flags->label);
if (!*monologue) if (!*monologue)
@ -1848,14 +1851,23 @@ out:
#ifdef WITH_TRANSCODING #ifdef WITH_TRANSCODING
static const char *play_media_select_party(struct call **call, struct call_monologue **monologue, static const char *play_media_select_party(struct call **call, GQueue *monologues,
bencode_item_t *input) bencode_item_t *input)
{ {
const char *err = media_block_match(call, monologue, NULL, input); struct call_monologue *monologue;
struct sdp_ng_flags flags;
g_queue_init(monologues);
const char *err = media_block_match(call, &monologue, &flags, input);
if (err) if (err)
return err; return err;
if (!*monologue) if (flags.all)
g_queue_append(monologues, &(*call)->monologues);
else if (!monologue)
return "No participant party specified"; return "No participant party specified";
else
g_queue_push_tail(monologues, monologue);
return NULL; return NULL;
} }
#endif #endif
@ -1865,14 +1877,17 @@ const char *call_play_media_ng(bencode_item_t *input, bencode_item_t *output) {
#ifdef WITH_TRANSCODING #ifdef WITH_TRANSCODING
str str; str str;
struct call *call; struct call *call;
struct call_monologue *monologue; GQueue monologues;
const char *err = NULL; const char *err = NULL;
long long db_id; long long db_id;
err = play_media_select_party(&call, &monologue, input); err = play_media_select_party(&call, &monologues, input);
if (err) if (err)
goto out; goto out;
for (GList *l = monologues.head; l; l = l->next) {
struct call_monologue *monologue = l->data;
if (!monologue->player) if (!monologue->player)
monologue->player = media_player_new(monologue); monologue->player = media_player_new(monologue);
@ -1895,12 +1910,14 @@ const char *call_play_media_ng(bencode_item_t *input, bencode_item_t *output) {
else else
goto out; goto out;
if (monologue->player->duration) if (l == monologues.head && monologue->player->duration)
bencode_dictionary_add_integer(output, "duration", monologue->player->duration); bencode_dictionary_add_integer(output, "duration", monologue->player->duration);
}
err = NULL; err = NULL;
out: out:
g_queue_clear(&monologues);
if (call) { if (call) {
rwlock_unlock_w(&call->master_lock); rwlock_unlock_w(&call->master_lock);
obj_put(call); obj_put(call);
@ -1915,21 +1932,27 @@ out:
const char *call_stop_media_ng(bencode_item_t *input, bencode_item_t *output) { const char *call_stop_media_ng(bencode_item_t *input, bencode_item_t *output) {
#ifdef WITH_TRANSCODING #ifdef WITH_TRANSCODING
struct call *call; struct call *call;
struct call_monologue *monologue; GQueue monologues;
const char *err = NULL; const char *err = NULL;
err = play_media_select_party(&call, &monologue, input); err = play_media_select_party(&call, &monologues, input);
if (err) if (err)
goto out; goto out;
for (GList *l = monologues.head; l; l = l->next) {
struct call_monologue *monologue = l->data;
err = "Not currently playing media";
if (!monologue->player) if (!monologue->player)
return "Not currently playing media"; goto out;
media_player_stop(monologue->player); media_player_stop(monologue->player);
}
err = NULL; err = NULL;
out: out:
g_queue_clear(&monologues);
if (call) { if (call) {
rwlock_unlock_w(&call->master_lock); rwlock_unlock_w(&call->master_lock);
obj_put(call); obj_put(call);
@ -1944,11 +1967,11 @@ out:
const char *call_play_dtmf_ng(bencode_item_t *input, bencode_item_t *output) { const char *call_play_dtmf_ng(bencode_item_t *input, bencode_item_t *output) {
#ifdef WITH_TRANSCODING #ifdef WITH_TRANSCODING
struct call *call; struct call *call;
struct call_monologue *monologue; GQueue monologues;
str str; str str;
const char *err = NULL; const char *err = NULL;
err = play_media_select_party(&call, &monologue, input); err = play_media_select_party(&call, &monologues, input);
if (err) if (err)
goto out; goto out;
@ -1998,6 +2021,9 @@ const char *call_play_dtmf_ng(bencode_item_t *input, bencode_item_t *output) {
if (volume > 0) if (volume > 0)
volume *= -1; volume *= -1;
for (GList *l = monologues.head; l; l = l->next) {
struct call_monologue *monologue = l->data;
// find a usable output media // find a usable output media
struct call_media *media; struct call_media *media;
for (GList *l = monologue->medias.head; l; l = l->next) { for (GList *l = monologue->medias.head; l; l = l->next) {
@ -2015,8 +2041,12 @@ const char *call_play_dtmf_ng(bencode_item_t *input, bencode_item_t *output) {
found:; found:;
err = dtmf_inject(media, code, volume, duration, pause); err = dtmf_inject(media, code, volume, duration, pause);
if (err)
break;
}
out: out:
g_queue_clear(&monologues);
if (call) { if (call) {
rwlock_unlock_w(&call->master_lock); rwlock_unlock_w(&call->master_lock);
obj_put(call); obj_put(call);

@ -72,13 +72,14 @@ GetOptions(
'blob-file=s' => \$options{'blob-file'}, 'blob-file=s' => \$options{'blob-file'},
'db-id=i' => \$options{'db-id'}, 'db-id=i' => \$options{'db-id'},
'T38=s@' => \$options{'T.38'}, 'T38=s@' => \$options{'T.38'},
'code=s' => \$options{'code'},
) or die; ) or die;
my $cmd = shift(@ARGV) or die; my $cmd = shift(@ARGV) or die;
my %packet = (command => $cmd); my %packet = (command => $cmd);
for my $x (split(/,/, 'from-tag,to-tag,call-id,transport protocol,media address,ICE,address family,DTLS,via-branch,media address,ptime,xmlrpc-callback,metadata,address,file,db-id')) { for my $x (split(/,/, 'from-tag,to-tag,call-id,transport protocol,media address,ICE,address family,DTLS,via-branch,media address,ptime,xmlrpc-callback,metadata,address,file,db-id,code')) {
defined($options{$x}) and $packet{$x} = \$options{$x}; defined($options{$x}) and $packet{$x} = \$options{$x};
} }
for my $x (split(/,/, 'TOS,delete-delay')) { for my $x (split(/,/, 'TOS,delete-delay')) {

Loading…
Cancel
Save