mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-25 06:00:36 +00:00 
			
		
		
		
	ari: Add events for playback and recording.
While there were events defined for playback and recording these were not actually sent. This change implements the to_json handlers which produces them. (closes issue ASTERISK-22710) Reported by: Jonathan Rose Review: https://reviewboard.asterisk.org/r/3026/ ........ Merged revisions 403119 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@403120 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
		| @@ -996,6 +996,15 @@ int ast_ari_validate_live_recording(struct ast_json *json) | ||||
| 	int has_state = 0; | ||||
|  | ||||
| 	for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { | ||||
| 		if (strcmp("cause", 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 LiveRecording field cause failed validation\n"); | ||||
| 				res = 0; | ||||
| 			} | ||||
| 		} else | ||||
| 		if (strcmp("format", ast_json_object_iter_key(iter)) == 0) { | ||||
| 			int prop_is_valid; | ||||
| 			has_format = 1; | ||||
| @@ -3292,20 +3301,9 @@ int ast_ari_validate_recording_failed(struct ast_json *json) | ||||
| { | ||||
| 	int res = 1; | ||||
| 	struct ast_json_iter *iter; | ||||
| 	int has_cause = 0; | ||||
| 	int has_recording = 0; | ||||
|  | ||||
| 	for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { | ||||
| 		if (strcmp("cause", ast_json_object_iter_key(iter)) == 0) { | ||||
| 			int prop_is_valid; | ||||
| 			has_cause = 1; | ||||
| 			prop_is_valid = ast_ari_validate_string( | ||||
| 				ast_json_object_iter_value(iter)); | ||||
| 			if (!prop_is_valid) { | ||||
| 				ast_log(LOG_ERROR, "ARI RecordingFailed field cause failed validation\n"); | ||||
| 				res = 0; | ||||
| 			} | ||||
| 		} else | ||||
| 		if (strcmp("recording", ast_json_object_iter_key(iter)) == 0) { | ||||
| 			int prop_is_valid; | ||||
| 			has_recording = 1; | ||||
| @@ -3324,11 +3322,6 @@ int ast_ari_validate_recording_failed(struct ast_json *json) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (!has_cause) { | ||||
| 		ast_log(LOG_ERROR, "ARI RecordingFailed missing required field cause\n"); | ||||
| 		res = 0; | ||||
| 	} | ||||
|  | ||||
| 	if (!has_recording) { | ||||
| 		ast_log(LOG_ERROR, "ARI RecordingFailed missing required field recording\n"); | ||||
| 		res = 0; | ||||
|   | ||||
| @@ -1032,6 +1032,7 @@ ari_validator ast_ari_validate_application_fn(void); | ||||
|  * - id: string (required) | ||||
|  * - technology: string (required) | ||||
|  * LiveRecording | ||||
|  * - cause: string | ||||
|  * - format: string (required) | ||||
|  * - name: string (required) | ||||
|  * - state: string (required) | ||||
| @@ -1167,7 +1168,6 @@ ari_validator ast_ari_validate_application_fn(void); | ||||
|  * - timestamp: Date | ||||
|  * - playback: Playback (required) | ||||
|  * RecordingFailed | ||||
|  * - cause: string (required) | ||||
|  * - recording: LiveRecording (required) | ||||
|  * RecordingFinished | ||||
|  * - recording: LiveRecording (required) | ||||
|   | ||||
| @@ -57,8 +57,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") | ||||
| #define SOUND_URI_SCHEME "sound:" | ||||
| #define RECORDING_URI_SCHEME "recording:" | ||||
|  | ||||
| STASIS_MESSAGE_TYPE_DEFN(stasis_app_playback_snapshot_type); | ||||
|  | ||||
| /*! Container of all current playbacks */ | ||||
| static struct ao2_container *playbacks; | ||||
|  | ||||
| @@ -87,6 +85,32 @@ struct stasis_app_playback { | ||||
| 	enum stasis_app_playback_state state; | ||||
| }; | ||||
|  | ||||
| static struct ast_json *playback_to_json(struct stasis_message *message, | ||||
| 	const struct stasis_message_sanitizer *sanitize) | ||||
| { | ||||
| 	struct ast_channel_blob *channel_blob = stasis_message_data(message); | ||||
| 	struct ast_json *blob = channel_blob->blob; | ||||
| 	const char *state = | ||||
| 		ast_json_string_get(ast_json_object_get(blob, "state")); | ||||
| 	const char *type; | ||||
|  | ||||
| 	if (!strcmp(state, "playing")) { | ||||
| 		type = "PlaybackStarted"; | ||||
| 	} else if (!strcmp(state, "done")) { | ||||
| 		type = "PlaybackFinished"; | ||||
| 	} else { | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	return ast_json_pack("{s: s, s: O}", | ||||
| 		"type", type, | ||||
| 		"playback", blob); | ||||
| } | ||||
|  | ||||
| STASIS_MESSAGE_TYPE_DEFN(stasis_app_playback_snapshot_type, | ||||
| 	.to_json = playback_to_json, | ||||
| ); | ||||
|  | ||||
| static void playback_dtor(void *obj) | ||||
| { | ||||
| 	struct stasis_app_playback *playback = obj; | ||||
|   | ||||
| @@ -49,8 +49,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") | ||||
| /*! Recording check is unimplemented. le sigh */ | ||||
| #define RECORDING_CHECK 0 | ||||
|  | ||||
| STASIS_MESSAGE_TYPE_DEFN(stasis_app_recording_snapshot_type); | ||||
|  | ||||
| /*! Container of all current recordings */ | ||||
| static struct ao2_container *recordings; | ||||
|  | ||||
| @@ -61,13 +59,40 @@ struct stasis_app_recording { | ||||
| 	char *absolute_name; | ||||
| 	/*! Control object for the channel we're recording */ | ||||
| 	struct stasis_app_control *control; | ||||
|  | ||||
| 	/*! Current state of the recording. */ | ||||
| 	enum stasis_app_recording_state state; | ||||
| 	/*! Indicates whether the recording is currently muted */ | ||||
| 	int muted:1; | ||||
| }; | ||||
|  | ||||
| static struct ast_json *recording_to_json(struct stasis_message *message, | ||||
| 	const struct stasis_message_sanitizer *sanitize) | ||||
| { | ||||
| 	struct ast_channel_blob *channel_blob = stasis_message_data(message); | ||||
| 	struct ast_json *blob = channel_blob->blob; | ||||
| 	const char *state = | ||||
| 		ast_json_string_get(ast_json_object_get(blob, "state")); | ||||
| 	const char *type; | ||||
|  | ||||
| 	if (!strcmp(state, "recording")) { | ||||
| 		type = "RecordingStarted"; | ||||
| 	} else if (!strcmp(state, "done") || !strcasecmp(state, "canceled")) { | ||||
| 		type = "RecordingFinished"; | ||||
| 	} else if (!strcmp(state, "failed")) { | ||||
| 		type = "RecordingFailed"; | ||||
| 	} else { | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	return ast_json_pack("{s: s, s: O}", | ||||
| 		"type", type, | ||||
| 		"recording", blob); | ||||
| } | ||||
|  | ||||
| STASIS_MESSAGE_TYPE_DEFN(stasis_app_recording_snapshot_type, | ||||
| 	.to_json = recording_to_json, | ||||
| ); | ||||
|  | ||||
| static int recording_hash(const void *obj, int flags) | ||||
| { | ||||
| 	const struct stasis_app_recording *recording = obj; | ||||
| @@ -183,7 +208,7 @@ enum ast_record_if_exists stasis_app_recording_if_exists_parse( | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| static void recording_publish(struct stasis_app_recording *recording) | ||||
| static void recording_publish(struct stasis_app_recording *recording, const char *cause) | ||||
| { | ||||
| 	RAII_VAR(struct ast_json *, json, NULL, ast_json_unref); | ||||
| 	RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup); | ||||
| @@ -196,6 +221,19 @@ static void recording_publish(struct stasis_app_recording *recording) | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	if (!ast_strlen_zero(cause)) { | ||||
| 		struct ast_json *failure_cause = ast_json_string_create(cause); | ||||
|  | ||||
| 		if (!failure_cause) { | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		if (ast_json_object_set(json, "cause", failure_cause)) { | ||||
| 			ast_json_unref(failure_cause); | ||||
| 			return; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	message = ast_channel_blob_create_from_cache( | ||||
| 		stasis_app_control_get_channel_id(recording->control), | ||||
| 		stasis_app_recording_snapshot_type(), json); | ||||
| @@ -206,11 +244,11 @@ static void recording_publish(struct stasis_app_recording *recording) | ||||
| 	stasis_app_control_publish(recording->control, message); | ||||
| } | ||||
|  | ||||
| static void recording_fail(struct stasis_app_recording *recording) | ||||
| static void recording_fail(struct stasis_app_recording *recording, const char *cause) | ||||
| { | ||||
| 	SCOPED_AO2LOCK(lock, recording); | ||||
| 	recording->state = STASIS_APP_RECORDING_STATE_FAILED; | ||||
| 	recording_publish(recording); | ||||
| 	recording_publish(recording, cause); | ||||
| } | ||||
|  | ||||
| static void recording_cleanup(struct stasis_app_recording *recording) | ||||
| @@ -233,7 +271,7 @@ static void *record_file(struct stasis_app_control *control, | ||||
|  | ||||
| 	if (stasis_app_get_bridge(control)) { | ||||
| 		ast_log(LOG_ERROR, "Cannot record channel while in bridge\n"); | ||||
| 		recording_fail(recording); | ||||
| 		recording_fail(recording, "Cannot record channel while in bridge"); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| @@ -255,13 +293,13 @@ static void *record_file(struct stasis_app_control *control, | ||||
| 	if (res != 0) { | ||||
| 		ast_debug(3, "%s: Failed to answer\n", | ||||
| 			ast_channel_uniqueid(chan)); | ||||
| 		recording_fail(recording); | ||||
| 		recording_fail(recording, "Failed to answer channel"); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | ||||
| 	ao2_lock(recording); | ||||
| 	recording->state = STASIS_APP_RECORDING_STATE_RECORDING; | ||||
| 	recording_publish(recording); | ||||
| 	recording_publish(recording, NULL); | ||||
| 	ao2_unlock(recording); | ||||
|  | ||||
| 	ast_play_and_record_full(chan, | ||||
| @@ -284,7 +322,7 @@ static void *record_file(struct stasis_app_control *control, | ||||
|  | ||||
| 	ao2_lock(recording); | ||||
| 	recording->state = STASIS_APP_RECORDING_STATE_COMPLETE; | ||||
| 	recording_publish(recording); | ||||
| 	recording_publish(recording, NULL); | ||||
| 	ao2_unlock(recording); | ||||
|  | ||||
| 	return NULL; | ||||
|   | ||||
| @@ -153,11 +153,6 @@ | ||||
| 					"type": "LiveRecording", | ||||
| 					"description": "Recording control object", | ||||
| 					"required": true | ||||
| 				}, | ||||
| 				"cause": { | ||||
| 					"type": "string", | ||||
| 					"description": "Cause for the recording failure", | ||||
| 					"required": true | ||||
| 				} | ||||
| 			} | ||||
| 		}, | ||||
|   | ||||
| @@ -307,6 +307,11 @@ | ||||
| 						] | ||||
| 					} | ||||
| 				}, | ||||
| 				"cause": { | ||||
| 					"required": false, | ||||
| 					"type": "string", | ||||
| 					"description": "Cause for recording failure if failed" | ||||
| 				}, | ||||
| 				"state": { | ||||
| 					"required": true, | ||||
| 					"type": "string" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user