feat: ARI "ChannelToneDetected" event

A stasis event is now produced when using the TONE_DETECT dialplan
function. This event is published over ARI using the ChannelToneDetected
event. This change does not make it available over AMI.

Fixes: #811

UserNote: Setting the TONE_DETECT dialplan function on a channel
in ARI will now cause a ChannelToneDetected ARI event to be raised
when the specified tone is detected.
pull/836/head
gibbz00 9 months ago committed by asterisk-org-access-app[bot]
parent 0f67c2696f
commit 99a5064a07

@ -69,6 +69,7 @@
; decline=ast_channel_agent_logoff_type
; decline=ast_channel_talking_start
; decline=ast_channel_talking_stop
; decline=ast_channel_tone_detect
; decline=ast_security_event_type
; decline=ast_named_acl_change_type
; decline=ast_local_bridge_type

@ -656,6 +656,14 @@ struct stasis_message_type *ast_channel_talking_start(void);
*/
struct stasis_message_type *ast_channel_talking_stop(void);
/*!
* \since 22.0.0
* \brief Message type for a channel tone detection
*
* \return A stasis message type
*/
struct stasis_message_type *ast_channel_tone_detect(void);
/*!
* \since 12
* \brief Publish in the \ref ast_channel_topic or \ref ast_channel_topic_all

@ -137,6 +137,7 @@
<enum name="ast_channel_agent_logoff_type" />
<enum name="ast_channel_talking_start" />
<enum name="ast_channel_talking_stop" />
<enum name="ast_channel_tone_detect" />
<enum name="ast_security_event_type" />
<enum name="ast_named_acl_change_type" />
<enum name="ast_local_bridge_type" />

@ -1592,6 +1592,13 @@ static struct ast_json *hold_to_json(struct stasis_message *message,
"channel", json_channel);
}
static struct ast_json *tone_detect_to_json(struct stasis_message *message,
const struct stasis_message_sanitizer *sanitize)
{
return channel_blob_to_json(message, "ChannelToneDetected", sanitize);
}
static struct ast_json *unhold_to_json(struct stasis_message *message,
const struct stasis_message_sanitizer *sanitize)
{
@ -1661,6 +1668,9 @@ STASIS_MESSAGE_TYPE_DEFN(ast_channel_talking_stop,
.to_ami = talking_stop_to_ami,
.to_json = talking_stop_to_json,
);
STASIS_MESSAGE_TYPE_DEFN(ast_channel_tone_detect,
.to_json = tone_detect_to_json,
);
/*! @} */
@ -1697,6 +1707,7 @@ static void stasis_channels_cleanup(void)
STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_agent_logoff_type);
STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_talking_start);
STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_talking_stop);
STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_tone_detect);
}
int ast_stasis_channels_init(void)
@ -1748,6 +1759,7 @@ int ast_stasis_channels_init(void)
res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_mixmonitor_mute_type);
res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_talking_start);
res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_talking_stop);
res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_tone_detect);
return res;
}

@ -4906,6 +4906,101 @@ ari_validator ast_ari_validate_channel_talking_started_fn(void)
return ast_ari_validate_channel_talking_started;
}
int ast_ari_validate_channel_tone_detected(struct ast_json *json)
{
int res = 1;
struct ast_json_iter *iter;
int has_type = 0;
int has_application = 0;
int has_timestamp = 0;
int has_channel = 0;
for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) {
if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) {
int prop_is_valid;
prop_is_valid = ast_ari_validate_string(
ast_json_object_iter_value(iter));
if (!prop_is_valid) {
ast_log(LOG_ERROR, "ARI ChannelToneDetected field asterisk_id failed validation\n");
res = 0;
}
} else
if (strcmp("type", ast_json_object_iter_key(iter)) == 0) {
int prop_is_valid;
has_type = 1;
prop_is_valid = ast_ari_validate_string(
ast_json_object_iter_value(iter));
if (!prop_is_valid) {
ast_log(LOG_ERROR, "ARI ChannelToneDetected field type failed validation\n");
res = 0;
}
} else
if (strcmp("application", ast_json_object_iter_key(iter)) == 0) {
int prop_is_valid;
has_application = 1;
prop_is_valid = ast_ari_validate_string(
ast_json_object_iter_value(iter));
if (!prop_is_valid) {
ast_log(LOG_ERROR, "ARI ChannelToneDetected field application failed validation\n");
res = 0;
}
} else
if (strcmp("timestamp", ast_json_object_iter_key(iter)) == 0) {
int prop_is_valid;
has_timestamp = 1;
prop_is_valid = ast_ari_validate_date(
ast_json_object_iter_value(iter));
if (!prop_is_valid) {
ast_log(LOG_ERROR, "ARI ChannelToneDetected field timestamp failed validation\n");
res = 0;
}
} else
if (strcmp("channel", ast_json_object_iter_key(iter)) == 0) {
int prop_is_valid;
has_channel = 1;
prop_is_valid = ast_ari_validate_channel(
ast_json_object_iter_value(iter));
if (!prop_is_valid) {
ast_log(LOG_ERROR, "ARI ChannelToneDetected field channel failed validation\n");
res = 0;
}
} else
{
ast_log(LOG_ERROR,
"ARI ChannelToneDetected has undocumented field %s\n",
ast_json_object_iter_key(iter));
res = 0;
}
}
if (!has_type) {
ast_log(LOG_ERROR, "ARI ChannelToneDetected missing required field type\n");
res = 0;
}
if (!has_application) {
ast_log(LOG_ERROR, "ARI ChannelToneDetected missing required field application\n");
res = 0;
}
if (!has_timestamp) {
ast_log(LOG_ERROR, "ARI ChannelToneDetected missing required field timestamp\n");
res = 0;
}
if (!has_channel) {
ast_log(LOG_ERROR, "ARI ChannelToneDetected missing required field channel\n");
res = 0;
}
return res;
}
ari_validator ast_ari_validate_channel_tone_detected_fn(void)
{
return ast_ari_validate_channel_tone_detected;
}
int ast_ari_validate_channel_unhold(struct ast_json *json)
{
int res = 1;
@ -5867,6 +5962,9 @@ int ast_ari_validate_event(struct ast_json *json)
if (strcmp("ChannelTalkingStarted", discriminator) == 0) {
return ast_ari_validate_channel_talking_started(json);
} else
if (strcmp("ChannelToneDetected", discriminator) == 0) {
return ast_ari_validate_channel_tone_detected(json);
} else
if (strcmp("ChannelUnhold", discriminator) == 0) {
return ast_ari_validate_channel_unhold(json);
} else
@ -6074,6 +6172,9 @@ int ast_ari_validate_message(struct ast_json *json)
if (strcmp("ChannelTalkingStarted", discriminator) == 0) {
return ast_ari_validate_channel_talking_started(json);
} else
if (strcmp("ChannelToneDetected", discriminator) == 0) {
return ast_ari_validate_channel_tone_detected(json);
} else
if (strcmp("ChannelUnhold", discriminator) == 0) {
return ast_ari_validate_channel_unhold(json);
} else

@ -911,6 +911,22 @@ int ast_ari_validate_channel_talking_started(struct ast_json *json);
*/
ari_validator ast_ari_validate_channel_talking_started_fn(void);
/*!
* \brief Validator for ChannelToneDetected.
*
* Tone was detected on the channel.
*
* \param json JSON object to validate.
* \retval True (non-zero) if valid.
* \retval False (zero) if invalid.
*/
int ast_ari_validate_channel_tone_detected(struct ast_json *json);
/*!
* \brief Function pointer to ast_ari_validate_channel_tone_detected().
*/
ari_validator ast_ari_validate_channel_tone_detected_fn(void);
/*!
* \brief Validator for ChannelUnhold.
*
@ -1605,6 +1621,12 @@ ari_validator ast_ari_validate_application_fn(void);
* - application: string (required)
* - timestamp: Date (required)
* - channel: Channel (required)
* ChannelToneDetected
* - asterisk_id: string
* - type: string (required)
* - application: string (required)
* - timestamp: Date (required)
* - channel: Channel (required)
* ChannelUnhold
* - asterisk_id: string
* - type: string (required)

@ -39,6 +39,7 @@
#include "asterisk/channel.h"
#include "asterisk/dsp.h"
#include "asterisk/pbx.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/audiohook.h"
#include "asterisk/app.h"
#include "asterisk/indications.h"
@ -355,6 +356,7 @@ static int detect_callback(struct ast_audiohook *audiohook, struct ast_channel *
{
struct ast_datastore *datastore = NULL;
struct detect_information *di = NULL;
struct stasis_message *message;
int match = 0;
/* If the audiohook is stopping it means the channel is shutting down.... but we let the datastore destroy take care of it */
@ -394,6 +396,16 @@ static int detect_callback(struct ast_audiohook *audiohook, struct ast_channel *
}
ast_debug(1, "TONE_DETECT just got a hit (#%d in this direction, waiting for %d total)\n", now, di->hitsrequired);
if (now >= di->hitsrequired) {
message = ast_channel_blob_create_from_cache(ast_channel_uniqueid(chan), ast_channel_tone_detect(), NULL);
if (!message) {
ast_log(LOG_ERROR, "Unable to publish tone detected event for ARI on channel '%s'", ast_channel_name(chan));
return 1;
} else {
stasis_publish(ast_channel_topic(chan), message);
ao2_ref(message, -1);
}
if (direction == AST_AUDIOHOOK_DIRECTION_READ && di->gotorx) {
ast_async_parseable_goto(chan, di->gotorx);
} else if (di->gototx) {

@ -178,6 +178,7 @@
"ChannelUserevent",
"ChannelHangupRequest",
"ChannelVarset",
"ChannelToneDetected",
"ChannelTalkingStarted",
"ChannelTalkingFinished",
"ChannelHold",
@ -759,6 +760,17 @@
}
}
},
"ChannelToneDetected": {
"id": "ChannelToneDetected",
"description": "Tone was detected on the channel.",
"properties": {
"channel": {
"required": true,
"type": "Channel",
"description": "The channel the tone was detected on."
}
}
},
"ChannelTalkingStarted": {
"id": "ChannelTalkingStarted",
"description": "Talking was detected on the channel.",

Loading…
Cancel
Save