[svn-commits] mjordan: trunk r414935 - in /trunk: ./ funcs/ include/asterisk/ main/ res/ari...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Fri May 30 07:43:00 CDT 2014


Author: mjordan
Date: Fri May 30 07:42:57 2014
New Revision: 414935

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=414935
Log:
TALK_DETECT: A channel function that raises events when talking is detected

This patch adds a new channel function TALK_DETECT that, when set on a
channel, causes events indicating the start/stop of talking on a channel to be
emitted to both AMI and ARI clients. 

The function allows setting both the silence threshold (the length of silence
after which we decide no one is talking) as well as the talking threshold (the
amount of energy that counts as talking). Parameters can be updated on a channel
after talk detection has been enabled, and talk detection can be removed at
any time.

The events raised by the function use a nomenclature similar to existing AMI/ARI
events.
For AMI: ChannelTalkingStart/ChannelTalkingStop
For ARI: ChannelTalkingStarted/ChannelTalkingFinished

Review: https://reviewboard.asterisk.org/r/3563/

#ASTERISK-23786 #close
Reported by: Matt Jordan
........

Merged revisions 414934 from http://svn.asterisk.org/svn/asterisk/branches/12

Added:
    trunk/funcs/func_talkdetect.c
      - copied unchanged from r414934, branches/12/funcs/func_talkdetect.c
Modified:
    trunk/   (props changed)
    trunk/CHANGES
    trunk/include/asterisk/stasis_channels.h
    trunk/main/audiohook.c
    trunk/main/stasis_channels.c
    trunk/res/ari/ari_model_validators.c
    trunk/res/ari/ari_model_validators.h
    trunk/rest-api/api-docs/events.json

Propchange: trunk/
------------------------------------------------------------------------------
Binary property 'branch-12-merged' - no diff available.

Modified: trunk/CHANGES
URL: http://svnview.digium.com/svn/asterisk/trunk/CHANGES?view=diff&rev=414935&r1=414934&r2=414935
==============================================================================
--- trunk/CHANGES (original)
+++ trunk/CHANGES Fri May 30 07:42:57 2014
@@ -30,6 +30,26 @@
    connect with an incoming caller after being alerted to the presence
    of the incoming caller.  The most likely reason this would happen is
    the agent did not acknowledge the call in time.
+
+AMI
+------------------
+ * New events have been added for the TALK_DETECT function. When the function
+   is used on a channel, ChannelTalkingStart/ChannelTalkingStop events will be
+   emitted to connected AMI clients indicating the start/stop of talking on
+   the channel.
+
+ARI
+------------------
+ * New event models have been aded for the TALK_DETECT function. When the
+   function is used on a channel, ChannelTalkingStarted/ChannelTalkingFinished
+   events will be emitted to connected WebSockets subscribed to the channel,
+   indicating the start/stop of talking on the channel.
+
+Functions
+------------------
+ * A new function, TALK_DETECT, has been added. When set on a channel, this
+   fucntion causes events indicating the starting/stoping of talking on said
+   channel to be emitted to both AMI and ARI clients.
 
 ------------------------------------------------------------------------------
 --- Functionality changes from Asterisk 12.2.0 to Asterisk 12.3.0 ------------

Modified: trunk/include/asterisk/stasis_channels.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/stasis_channels.h?view=diff&rev=414935&r1=414934&r2=414935
==============================================================================
--- trunk/include/asterisk/stasis_channels.h (original)
+++ trunk/include/asterisk/stasis_channels.h Fri May 30 07:42:57 2014
@@ -500,6 +500,22 @@
 struct stasis_message_type *ast_channel_moh_stop_type(void);
 
 /*!
+ * \since 12.4.0
+ * \brief Message type for a channel starting talking
+ *
+ * \retval A stasis message type
+ */
+struct stasis_message_type *ast_channel_talking_start(void);
+
+/*!
+ * \since 12.4.0
+ * \brief Message type for a channel stopping talking
+ *
+ * \retval A stasis message type
+ */
+struct stasis_message_type *ast_channel_talking_stop(void);
+
+/*!
  * \since 12
  * \brief Publish in the \ref ast_channel_topic or \ref ast_channel_topic_all
  * topics a stasis message for the channels involved in a dial operation.

Modified: trunk/main/audiohook.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/audiohook.c?view=diff&rev=414935&r1=414934&r2=414935
==============================================================================
--- trunk/main/audiohook.c (original)
+++ trunk/main/audiohook.c Fri May 30 07:42:57 2014
@@ -874,17 +874,15 @@
 			}
 			audiohook_set_internal_rate(audiohook, audiohook_list->list_internal_samp_rate, 1);
 			/* Feed in frame to manipulation. */
-			if (audiohook->manipulate_callback(audiohook, chan, middle_frame, direction)) {
-				/* XXX IGNORE FAILURE */
-
+			if (!audiohook->manipulate_callback(audiohook, chan, middle_frame, direction)) {
 				/* If the manipulation fails then the frame will be returned in its original state.
 				 * Since there are potentially more manipulator callbacks in the list, no action should
 				 * be taken here to exit early. */
+				 middle_frame_manipulated = 1;
 			}
 			ast_audiohook_unlock(audiohook);
 		}
 		AST_LIST_TRAVERSE_SAFE_END;
-		middle_frame_manipulated = 1;
 	}
 
 	/* ---Part_3: Decide what to do with the end_frame (whether to transcode or not) */

Modified: trunk/main/stasis_channels.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/stasis_channels.c?view=diff&rev=414935&r1=414934&r2=414935
==============================================================================
--- trunk/main/stasis_channels.c (original)
+++ trunk/main/stasis_channels.c Fri May 30 07:42:57 2014
@@ -85,6 +85,34 @@
 			</see-also>
 		</managerEventInstance>
 	</managerEvent>
+	<managerEvent language="en_US" name="ChannelTalkingStart">
+		<managerEventInstance class="EVENT_FLAG_CLASS">
+			<synopsis>Raised when talking is detected on a channel.</synopsis>
+			<syntax>
+				<channel_snapshot/>
+			</syntax>
+			<see-also>
+				<ref type="function">TALK_DETECT</ref>
+				<ref type="managerEvent">ChannelTalkingStop</ref>
+			</see-also>
+		</managerEventInstance>
+	</managerEvent>
+	<managerEvent language="en_US" name="ChannelTalkingStop">
+		<managerEventInstance class="EVENT_FLAG_CLASS">
+			<synopsis>Raised when talking is no longer detected on a channel.</synopsis>
+			<syntax>
+				<channel_snapshot/>
+				<parameter name="Duration">
+					<para>The length in time, in milliseconds, that talking was
+					detected on the channel.</para>
+				</parameter>
+			</syntax>
+			<see-also>
+				<ref type="function">TALK_DETECT</ref>
+				<ref type="managerEvent">ChannelTalkingStart</ref>
+			</see-also>
+		</managerEventInstance>
+	</managerEvent>
 ***/
 
 #define NUM_MULTI_CHANNEL_BLOB_BUCKETS 7
@@ -972,6 +1000,58 @@
 	}
 
 	return json;
+}
+
+static struct ast_manager_event_blob *talking_start_to_ami(struct stasis_message *msg)
+{
+	struct ast_str *channel_string;
+	struct ast_channel_blob *obj = stasis_message_data(msg);
+	struct ast_manager_event_blob *blob;
+
+	channel_string = ast_manager_build_channel_state_string(obj->snapshot);
+	if (!channel_string) {
+		return NULL;
+	}
+
+	blob = ast_manager_event_blob_create(EVENT_FLAG_CALL, "ChannelTalkingStart",
+	                                     "%s", ast_str_buffer(channel_string));
+	ast_free(channel_string);
+
+	return blob;
+}
+
+static struct ast_json *talking_start_to_json(struct stasis_message *message,
+	const struct stasis_message_sanitizer *sanitize)
+{
+	return channel_blob_to_json(message, "ChannelTalkingStarted", sanitize);
+}
+
+static struct ast_manager_event_blob *talking_stop_to_ami(struct stasis_message *msg)
+{
+	struct ast_str *channel_string;
+	struct ast_channel_blob *obj = stasis_message_data(msg);
+	int duration = ast_json_integer_get(ast_json_object_get(obj->blob, "duration"));
+	struct ast_manager_event_blob *blob;
+
+	channel_string = ast_manager_build_channel_state_string(obj->snapshot);
+	if (!channel_string) {
+		return NULL;
+	}
+
+	blob = ast_manager_event_blob_create(EVENT_FLAG_CALL, "ChannelTalkingStop",
+	                                     "%s"
+	                                     "Duration: %d\r\n",
+	                                     ast_str_buffer(channel_string),
+	                                     duration);
+	ast_free(channel_string);
+
+	return blob;
+}
+
+static struct ast_json *talking_stop_to_json(struct stasis_message *message,
+	const struct stasis_message_sanitizer *sanitize)
+{
+	return channel_blob_to_json(message, "ChannelTalkingFinished", sanitize);
 }
 
 /*!
@@ -1008,6 +1088,14 @@
 STASIS_MESSAGE_TYPE_DEFN(ast_channel_agent_logoff_type,
 	.to_ami = agent_logoff_to_ami,
 	);
+STASIS_MESSAGE_TYPE_DEFN(ast_channel_talking_start,
+	.to_ami = talking_start_to_ami,
+	.to_json = talking_start_to_json,
+	);
+STASIS_MESSAGE_TYPE_DEFN(ast_channel_talking_stop,
+	.to_ami = talking_stop_to_ami,
+	.to_json = talking_stop_to_json,
+	);
 
 /*! @} */
 
@@ -1038,6 +1126,8 @@
 	STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_monitor_stop_type);
 	STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_agent_login_type);
 	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);
 }
 
 int ast_stasis_channels_init(void)
@@ -1084,6 +1174,8 @@
 	res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_moh_stop_type);
 	res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_monitor_start_type);
 	res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_monitor_stop_type);
+	res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_talking_start);
+	res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_talking_stop);
 
 	return res;
 }

Modified: trunk/res/ari/ari_model_validators.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/ari/ari_model_validators.c?view=diff&rev=414935&r1=414934&r2=414935
==============================================================================
--- trunk/res/ari/ari_model_validators.c (original)
+++ trunk/res/ari/ari_model_validators.c Fri May 30 07:42:57 2014
@@ -3070,6 +3070,180 @@
 	return ast_ari_validate_channel_state_change;
 }
 
+int ast_ari_validate_channel_talking_finished(struct ast_json *json)
+{
+	int res = 1;
+	struct ast_json_iter *iter;
+	int has_type = 0;
+	int has_application = 0;
+	int has_channel = 0;
+	int has_duration = 0;
+
+	for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) {
+		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 ChannelTalkingFinished 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 ChannelTalkingFinished field application failed validation\n");
+				res = 0;
+			}
+		} else
+		if (strcmp("timestamp", ast_json_object_iter_key(iter)) == 0) {
+			int prop_is_valid;
+			prop_is_valid = ast_ari_validate_date(
+				ast_json_object_iter_value(iter));
+			if (!prop_is_valid) {
+				ast_log(LOG_ERROR, "ARI ChannelTalkingFinished 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 ChannelTalkingFinished field channel failed validation\n");
+				res = 0;
+			}
+		} else
+		if (strcmp("duration", ast_json_object_iter_key(iter)) == 0) {
+			int prop_is_valid;
+			has_duration = 1;
+			prop_is_valid = ast_ari_validate_int(
+				ast_json_object_iter_value(iter));
+			if (!prop_is_valid) {
+				ast_log(LOG_ERROR, "ARI ChannelTalkingFinished field duration failed validation\n");
+				res = 0;
+			}
+		} else
+		{
+			ast_log(LOG_ERROR,
+				"ARI ChannelTalkingFinished has undocumented field %s\n",
+				ast_json_object_iter_key(iter));
+			res = 0;
+		}
+	}
+
+	if (!has_type) {
+		ast_log(LOG_ERROR, "ARI ChannelTalkingFinished missing required field type\n");
+		res = 0;
+	}
+
+	if (!has_application) {
+		ast_log(LOG_ERROR, "ARI ChannelTalkingFinished missing required field application\n");
+		res = 0;
+	}
+
+	if (!has_channel) {
+		ast_log(LOG_ERROR, "ARI ChannelTalkingFinished missing required field channel\n");
+		res = 0;
+	}
+
+	if (!has_duration) {
+		ast_log(LOG_ERROR, "ARI ChannelTalkingFinished missing required field duration\n");
+		res = 0;
+	}
+
+	return res;
+}
+
+ari_validator ast_ari_validate_channel_talking_finished_fn(void)
+{
+	return ast_ari_validate_channel_talking_finished;
+}
+
+int ast_ari_validate_channel_talking_started(struct ast_json *json)
+{
+	int res = 1;
+	struct ast_json_iter *iter;
+	int has_type = 0;
+	int has_application = 0;
+	int has_channel = 0;
+
+	for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) {
+		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 ChannelTalkingStarted 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 ChannelTalkingStarted field application failed validation\n");
+				res = 0;
+			}
+		} else
+		if (strcmp("timestamp", ast_json_object_iter_key(iter)) == 0) {
+			int prop_is_valid;
+			prop_is_valid = ast_ari_validate_date(
+				ast_json_object_iter_value(iter));
+			if (!prop_is_valid) {
+				ast_log(LOG_ERROR, "ARI ChannelTalkingStarted 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 ChannelTalkingStarted field channel failed validation\n");
+				res = 0;
+			}
+		} else
+		{
+			ast_log(LOG_ERROR,
+				"ARI ChannelTalkingStarted has undocumented field %s\n",
+				ast_json_object_iter_key(iter));
+			res = 0;
+		}
+	}
+
+	if (!has_type) {
+		ast_log(LOG_ERROR, "ARI ChannelTalkingStarted missing required field type\n");
+		res = 0;
+	}
+
+	if (!has_application) {
+		ast_log(LOG_ERROR, "ARI ChannelTalkingStarted missing required field application\n");
+		res = 0;
+	}
+
+	if (!has_channel) {
+		ast_log(LOG_ERROR, "ARI ChannelTalkingStarted missing required field channel\n");
+		res = 0;
+	}
+
+	return res;
+}
+
+ari_validator ast_ari_validate_channel_talking_started_fn(void)
+{
+	return ast_ari_validate_channel_talking_started;
+}
+
 int ast_ari_validate_channel_userevent(struct ast_json *json)
 {
 	int res = 1;
@@ -3647,6 +3821,12 @@
 	if (strcmp("ChannelStateChange", discriminator) == 0) {
 		return ast_ari_validate_channel_state_change(json);
 	} else
+	if (strcmp("ChannelTalkingFinished", discriminator) == 0) {
+		return ast_ari_validate_channel_talking_finished(json);
+	} else
+	if (strcmp("ChannelTalkingStarted", discriminator) == 0) {
+		return ast_ari_validate_channel_talking_started(json);
+	} else
 	if (strcmp("ChannelUserevent", discriminator) == 0) {
 		return ast_ari_validate_channel_userevent(json);
 	} else
@@ -3805,6 +3985,12 @@
 	} else
 	if (strcmp("ChannelStateChange", discriminator) == 0) {
 		return ast_ari_validate_channel_state_change(json);
+	} else
+	if (strcmp("ChannelTalkingFinished", discriminator) == 0) {
+		return ast_ari_validate_channel_talking_finished(json);
+	} else
+	if (strcmp("ChannelTalkingStarted", discriminator) == 0) {
+		return ast_ari_validate_channel_talking_started(json);
 	} else
 	if (strcmp("ChannelUserevent", discriminator) == 0) {
 		return ast_ari_validate_channel_userevent(json);

Modified: trunk/res/ari/ari_model_validators.h
URL: http://svnview.digium.com/svn/asterisk/trunk/res/ari/ari_model_validators.h?view=diff&rev=414935&r1=414934&r2=414935
==============================================================================
--- trunk/res/ari/ari_model_validators.h (original)
+++ trunk/res/ari/ari_model_validators.h Fri May 30 07:42:57 2014
@@ -789,6 +789,42 @@
  * See \ref ast_ari_model_validators.h for more details.
  */
 ari_validator ast_ari_validate_channel_state_change_fn(void);
+
+/*!
+ * \brief Validator for ChannelTalkingFinished.
+ *
+ * Talking is no longer detected on the channel.
+ *
+ * \param json JSON object to validate.
+ * \returns True (non-zero) if valid.
+ * \returns False (zero) if invalid.
+ */
+int ast_ari_validate_channel_talking_finished(struct ast_json *json);
+
+/*!
+ * \brief Function pointer to ast_ari_validate_channel_talking_finished().
+ *
+ * See \ref ast_ari_model_validators.h for more details.
+ */
+ari_validator ast_ari_validate_channel_talking_finished_fn(void);
+
+/*!
+ * \brief Validator for ChannelTalkingStarted.
+ *
+ * Talking was detected on the channel.
+ *
+ * \param json JSON object to validate.
+ * \returns True (non-zero) if valid.
+ * \returns False (zero) if invalid.
+ */
+int ast_ari_validate_channel_talking_started(struct ast_json *json);
+
+/*!
+ * \brief Function pointer to ast_ari_validate_channel_talking_started().
+ *
+ * See \ref ast_ari_model_validators.h for more details.
+ */
+ari_validator ast_ari_validate_channel_talking_started_fn(void);
 
 /*!
  * \brief Validator for ChannelUserevent.
@@ -1274,6 +1310,17 @@
  * - application: string (required)
  * - timestamp: Date
  * - channel: Channel (required)
+ * ChannelTalkingFinished
+ * - type: string (required)
+ * - application: string (required)
+ * - timestamp: Date
+ * - channel: Channel (required)
+ * - duration: int (required)
+ * ChannelTalkingStarted
+ * - type: string (required)
+ * - application: string (required)
+ * - timestamp: Date
+ * - channel: Channel (required)
  * ChannelUserevent
  * - type: string (required)
  * - application: string (required)

Modified: trunk/rest-api/api-docs/events.json
URL: http://svnview.digium.com/svn/asterisk/trunk/rest-api/api-docs/events.json?view=diff&rev=414935&r1=414934&r2=414935
==============================================================================
--- trunk/rest-api/api-docs/events.json (original)
+++ trunk/rest-api/api-docs/events.json Fri May 30 07:42:57 2014
@@ -159,6 +159,8 @@
 				"ChannelUserevent",
 				"ChannelHangupRequest",
 				"ChannelVarset",
+				"ChannelTalkingStarted",
+				"ChannelTalkingFinished",
 				"EndpointStateChange",
 				"Dial",
 				"StasisEnd",
@@ -572,6 +574,33 @@
 				}
 			}
 		},
+		"ChannelTalkingStarted": {
+			"id": "ChannelTalkingStarted",
+			"description": "Talking was detected on the channel.",
+			"properties": {
+				"channel": {
+					"required": true,
+					"type": "Channel",
+					"description": "The channel on which talking started."
+				}
+			}
+		},
+		"ChannelTalkingFinished": {
+			"id": "ChannelTalkingFinished",
+			"description": "Talking is no longer detected on the channel.",
+			"properties": {
+				"channel": {
+					"required": true,
+					"type": "Channel",
+					"description": "The channel on which talking completed."
+				},
+				"duration": {
+					"required": true,
+					"type": "int",
+					"description": "The length of time, in milliseconds, that talking was detected on the channel"
+				}
+			}
+		},
 		"EndpointStateChange": {
 			"id": "EndpointStateChange",
 			"description": "Endpoint state changed.",




More information about the svn-commits mailing list