Asterisk - The Open Source Telephony Project GIT-master-70eff7f
Loading...
Searching...
No Matches
Data Structures | Macros | Typedefs | Functions | Variables
res_stasis_recording.c File Reference

res_stasis recording support. More...

#include "asterisk.h"
#include "asterisk/dsp.h"
#include "asterisk/file.h"
#include "asterisk/module.h"
#include "asterisk/paths.h"
#include "asterisk/bridge.h"
#include "asterisk/stasis_app_impl.h"
#include "asterisk/stasis_app_recording.h"
#include "asterisk/stasis_channels.h"
Include dependency graph for res_stasis_recording.c:

Go to the source code of this file.

Data Structures

struct  stasis_app_recording
 

Macros

#define RECORDING_BUCKETS   127
 
#define RECORDING_CHECK   0
 
#define RECORDING_COMMENT   NULL
 

Typedefs

typedef int(* recording_operation_cb) (struct stasis_app_recording *recording)
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static enum stasis_app_control_channel_result check_rule_recording (const struct stasis_app_control *control)
 
static int load_module (void)
 
static int record_file (struct stasis_app_control *control, struct ast_channel *chan, void *data)
 
static int recording_cancel (struct stasis_app_recording *recording)
 
static void recording_cleanup (void *data)
 
static int recording_cmp (void *obj, void *arg, int flags)
 
static int recording_disregard (struct stasis_app_recording *recording)
 
static void recording_dtor (void *obj)
 
static void recording_fail (struct stasis_app_control *control, struct stasis_app_recording *recording, const char *cause)
 
static int recording_hash (const void *obj, int flags)
 
static int recording_mute (struct stasis_app_recording *recording)
 
static int recording_noop (struct stasis_app_recording *recording)
 
static void recording_options_dtor (void *obj)
 
static int recording_pause (struct stasis_app_recording *recording)
 
static void recording_publish (struct stasis_app_recording *recording, const char *cause)
 
static void recording_set_state (struct stasis_app_recording *recording, enum stasis_app_recording_state state, const char *cause)
 
static int recording_stop (struct stasis_app_recording *recording)
 
static struct ast_jsonrecording_to_json (struct stasis_message *message, const struct stasis_message_sanitizer *sanitize)
 
static int recording_unmute (struct stasis_app_recording *recording)
 
static int recording_unpause (struct stasis_app_recording *recording)
 
struct stasis_app_recordingstasis_app_control_record (struct stasis_app_control *control, struct stasis_app_recording_options *options)
 Record media from a channel.
 
struct stasis_app_recordingstasis_app_recording_find_by_name (const char *name)
 Finds the recording object with the given name.
 
const char * stasis_app_recording_get_name (struct stasis_app_recording *recording)
 Gets the unique name of a recording object.
 
enum stasis_app_recording_state stasis_app_recording_get_state (struct stasis_app_recording *recording)
 Gets the current state of a recording operation.
 
enum ast_record_if_exists stasis_app_recording_if_exists_parse (const char *str)
 Parse a string into the if_exists enum.
 
enum stasis_app_recording_oper_results stasis_app_recording_operation (struct stasis_app_recording *recording, enum stasis_app_recording_media_operation operation)
 Controls the media for a given recording operation.
 
struct stasis_app_recording_optionsstasis_app_recording_options_create (const char *name, const char *format)
 Allocate a recording options object.
 
char stasis_app_recording_termination_parse (const char *str)
 Parse a string into the recording termination enum.
 
struct ast_jsonstasis_app_recording_to_json (const struct stasis_app_recording *recording)
 Construct a JSON model of a recording.
 
 STASIS_MESSAGE_TYPE_DEFN (stasis_app_recording_snapshot_type,.to_json=recording_to_json,)
 
static const char * state_to_string (enum stasis_app_recording_state state)
 
static int toggle_recording_mute (struct stasis_app_recording *recording, int desired_mute_state)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Stasis application recording support" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .requires = "res_stasis", .load_pri = AST_MODPRI_APP_DEPEND }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
recording_operation_cb operations [STASIS_APP_RECORDING_STATE_MAX][STASIS_APP_RECORDING_OPER_MAX]
 
static struct ao2_containerrecordings
 
static struct stasis_app_control_rule rule_recording
 

Detailed Description

res_stasis recording support.

Author
David M. Lee, II dlee@.nosp@m.digi.nosp@m.um.co.nosp@m.m

Definition in file res_stasis_recording.c.

Macro Definition Documentation

◆ RECORDING_BUCKETS

#define RECORDING_BUCKETS   127

Number of hash buckets for recording container. Keep it prime!

Definition at line 43 of file res_stasis_recording.c.

◆ RECORDING_CHECK

#define RECORDING_CHECK   0

Recording check is unimplemented. le sigh

Definition at line 49 of file res_stasis_recording.c.

◆ RECORDING_COMMENT

#define RECORDING_COMMENT   NULL

Comment is ignored by most formats, so we will ignore it, too.

Definition at line 46 of file res_stasis_recording.c.

Typedef Documentation

◆ recording_operation_cb

typedef int(* recording_operation_cb) (struct stasis_app_recording *recording)

Definition at line 519 of file res_stasis_recording.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 674 of file res_stasis_recording.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 674 of file res_stasis_recording.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 674 of file res_stasis_recording.c.

◆ check_rule_recording()

static enum stasis_app_control_channel_result check_rule_recording ( const struct stasis_app_control control)
static

Definition at line 262 of file res_stasis_recording.c.

264{
266}
@ STASIS_APP_CHANNEL_RECORDING
Definition stasis_app.h:841

References STASIS_APP_CHANNEL_RECORDING.

◆ load_module()

static int load_module ( void  )
static

Definition at line 642 of file res_stasis_recording.c.

643{
644 int r;
645
647 if (r != 0) {
649 }
650
653 if (!recordings) {
656 }
658}
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition astobj2.h:363
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
Definition astobj2.h:1303
@ AST_MODULE_LOAD_SUCCESS
Definition module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition module.h:78
static int recording_hash(const void *obj, int flags)
#define RECORDING_BUCKETS
static struct ao2_container * recordings
static int recording_cmp(void *obj, void *arg, int flags)
#define NULL
Definition resample.c:96
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
Definition stasis.h:1546
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
Definition stasis.h:1524
struct stasis_message_type * stasis_app_recording_snapshot_type(void)
Message type for recording updates. The data is an ast_channel_blob.

References AO2_ALLOC_OPT_LOCK_MUTEX, ao2_container_alloc_hash, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, NULL, RECORDING_BUCKETS, recording_cmp(), recording_hash(), recordings, stasis_app_recording_snapshot_type(), STASIS_MESSAGE_TYPE_CLEANUP, and STASIS_MESSAGE_TYPE_INIT.

◆ record_file()

static int record_file ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
)
static

Definition at line 297 of file res_stasis_recording.c.

299{
300 struct stasis_app_recording *recording = data;
301 struct ast_bridge *bridge;
302 char *acceptdtmf;
303 int res;
304
305 ast_assert(recording != NULL);
306
307 /*
308 * Recording is not allowed while the channel is in a "real" bridge,
309 * but ARI places an originated channel into an internal, invisible
310 * holding bridge (the dial bridge) while dialing. That bridge is not
311 * a bridge the application created - it is flagged invisible - so
312 * recording must still be permitted there. Otherwise, channels.record
313 * fails with "Cannot record channel while in bridge" even though the
314 * application never joined the channel to a bridge of its own.
315 * See GH issue #2044.
316 */
317 bridge = stasis_app_get_bridge(control);
318 if (bridge && !ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_INVISIBLE)) {
319 ast_log(LOG_ERROR, "Cannot record channel while in bridge\n");
320 recording_fail(control, recording, "Cannot record channel while in bridge");
321 return -1;
322 }
323
324 switch (recording->options->terminate_on) {
327 acceptdtmf = "";
328 break;
330 acceptdtmf = "#*0123456789abcd";
331 break;
332 default:
333 acceptdtmf = ast_alloca(2);
334 acceptdtmf[0] = recording->options->terminate_on;
335 acceptdtmf[1] = '\0';
336 }
337
338 res = ast_auto_answer(chan);
339 if (res != 0) {
340 ast_debug(3, "%s: Failed to answer\n",
342 recording_fail(control, recording, "Failed to answer channel");
343 return -1;
344 }
345
349 NULL, /* playfile */
350 recording->absolute_name,
351 recording->options->max_duration_seconds,
352 recording->options->format,
353 &recording->duration.total,
354 recording->options->max_silence_seconds ? &recording->duration.energy_only : NULL,
355 recording->options->beep,
356 -1, /* silencethreshold */
357 recording->options->max_silence_seconds * 1000,
358 NULL, /* path */
359 acceptdtmf,
360 NULL, /* canceldtmf */
361 1, /* skip_confirmation_sound */
362 recording->options->if_exists);
363
364 ast_debug(3, "%s: Recording complete\n", ast_channel_uniqueid(chan));
365
368
370
371 return 0;
372}
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition astmm.h:288
#define ast_log
Definition astobj2.c:42
@ AST_BRIDGE_FLAG_INVISIBLE
int ast_auto_answer(struct ast_channel *chan)
Answer a channel, if it's not already answered.
Definition channel.c:2811
const char * ast_channel_uniqueid(const struct ast_channel *chan)
int ast_play_and_record_full(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime_sec, const char *fmt, int *duration, int *sound_duration, int beep, int silencethreshold, int maxsilence_ms, const char *path, const char *acceptdtmf, const char *canceldtmf, int skip_confirmation_sound, enum ast_record_if_exists if_exists)
Record a file based on input from a channel This function will play "auth-thankyou" upon successful r...
Definition main/app.c:2150
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
static struct stasis_app_control_rule rule_recording
static void recording_fail(struct stasis_app_control *control, struct stasis_app_recording *recording, const char *cause)
static void recording_set_state(struct stasis_app_recording *recording, enum stasis_app_recording_state state, const char *cause)
struct ast_bridge * stasis_app_get_bridge(struct stasis_app_control *control)
Gets the bridge currently associated with a control object.
Definition control.c:993
void stasis_app_control_unregister_add_rule(struct stasis_app_control *control, struct stasis_app_control_rule *rule)
UnRegister an add channel to bridge rule.
Definition control.c:232
#define STASIS_APP_RECORDING_TERMINATE_NONE
#define STASIS_APP_RECORDING_TERMINATE_ANY
@ STASIS_APP_RECORDING_STATE_COMPLETE
@ STASIS_APP_RECORDING_STATE_RECORDING
#define STASIS_APP_RECORDING_TERMINATE_INVALID
Structure that contains information about a bridge.
Definition bridge.h:355
struct ast_flags feature_flags
Definition bridge.h:375
struct stasis_app_recording::@521 duration
struct stasis_app_recording_options * options
static struct test_options options
#define ast_test_flag(p, flag)
Definition utils.h:64
#define ast_assert(a)
Definition utils.h:779

References stasis_app_recording::absolute_name, ast_alloca, ast_assert, ast_auto_answer(), AST_BRIDGE_FLAG_INVISIBLE, ast_channel_uniqueid(), ast_debug, ast_log, ast_play_and_record_full(), ast_test_flag, stasis_app_recording_options::beep, stasis_app_recording::duration, stasis_app_recording::energy_only, ast_bridge::feature_flags, stasis_app_recording_options::format, stasis_app_recording_options::if_exists, LOG_ERROR, stasis_app_recording_options::max_duration_seconds, stasis_app_recording_options::max_silence_seconds, NULL, stasis_app_recording::options, recording_fail(), recording_set_state(), rule_recording, stasis_app_control_unregister_add_rule(), stasis_app_get_bridge(), STASIS_APP_RECORDING_STATE_COMPLETE, STASIS_APP_RECORDING_STATE_RECORDING, STASIS_APP_RECORDING_TERMINATE_ANY, STASIS_APP_RECORDING_TERMINATE_INVALID, STASIS_APP_RECORDING_TERMINATE_NONE, stasis_app_recording_options::terminate_on, and stasis_app_recording::total.

Referenced by stasis_app_control_record().

◆ recording_cancel()

static int recording_cancel ( struct stasis_app_recording recording)
static

Definition at line 532 of file res_stasis_recording.c.

533{
534 int res = 0;
538 res |= ast_filedelete(recording->absolute_name, NULL);
539 return res;
540}
int ast_filedelete(const char *filename, const char *fmt)
Deletes a file.
Definition file.c:1168
@ AST_CONTROL_RECORD_CANCEL
int stasis_app_control_queue_control(struct stasis_app_control *control, enum ast_control_frame_type frame_type)
Queue a control frame without payload.
Definition control.c:1518
@ STASIS_APP_RECORDING_STATE_CANCELED
enum stasis_app_recording_state state
struct stasis_app_control * control

References stasis_app_recording::absolute_name, AST_CONTROL_RECORD_CANCEL, ast_filedelete(), stasis_app_recording::control, NULL, stasis_app_control_queue_control(), STASIS_APP_RECORDING_STATE_CANCELED, and stasis_app_recording::state.

◆ recording_cleanup()

static void recording_cleanup ( void *  data)
static

Definition at line 288 of file res_stasis_recording.c.

289{
290 struct stasis_app_recording *recording = data;
291
292 ao2_unlink_flags(recordings, recording,
294 ao2_ref(recording, -1);
295}
#define OBJ_POINTER
Definition astobj2.h:1150
#define ao2_unlink_flags(container, obj, flags)
Remove an object from a container.
Definition astobj2.h:1600
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition astobj2.h:459
@ OBJ_NODATA
Definition astobj2.h:1044
@ OBJ_UNLINK
Definition astobj2.h:1039

References ao2_ref, ao2_unlink_flags, OBJ_NODATA, OBJ_POINTER, OBJ_UNLINK, and recordings.

Referenced by stasis_app_control_record().

◆ recording_cmp()

static int recording_cmp ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 110 of file res_stasis_recording.c.

111{
112 struct stasis_app_recording *lhs = obj;
113 struct stasis_app_recording *rhs = arg;
114 const char *rhs_id = flags & OBJ_KEY ? arg : rhs->options->name;
115
116 if (strcmp(lhs->options->name, rhs_id) == 0) {
117 return CMP_MATCH | CMP_STOP;
118 } else {
119 return 0;
120 }
121}
@ CMP_MATCH
Definition astobj2.h:1027
@ CMP_STOP
Definition astobj2.h:1028
#define OBJ_KEY
Definition astobj2.h:1151

References CMP_MATCH, CMP_STOP, stasis_app_recording_options::name, OBJ_KEY, and stasis_app_recording::options.

Referenced by load_module().

◆ recording_disregard()

static int recording_disregard ( struct stasis_app_recording recording)
static

Definition at line 526 of file res_stasis_recording.c.

527{
529 return 0;
530}

References STASIS_APP_RECORDING_STATE_CANCELED, and stasis_app_recording::state.

◆ recording_dtor()

static void recording_dtor ( void *  obj)
static

Definition at line 374 of file res_stasis_recording.c.

375{
376 struct stasis_app_recording *recording = obj;
377
378 ast_free(recording->absolute_name);
379 ao2_cleanup(recording->control);
380 ao2_cleanup(recording->options);
381}
#define ast_free(a)
Definition astmm.h:180
#define ao2_cleanup(obj)
Definition astobj2.h:1934

References stasis_app_recording::absolute_name, ao2_cleanup, ast_free, stasis_app_recording::control, and stasis_app_recording::options.

Referenced by stasis_app_control_record().

◆ recording_fail()

static void recording_fail ( struct stasis_app_control control,
struct stasis_app_recording recording,
const char *  cause 
)
static

◆ recording_hash()

static int recording_hash ( const void *  obj,
int  flags 
)
static

Definition at line 103 of file res_stasis_recording.c.

104{
105 const struct stasis_app_recording *recording = obj;
106 const char *id = flags & OBJ_KEY ? obj : recording->options->name;
107 return ast_str_hash(id);
108}
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
Definition strings.h:1259

References ast_str_hash(), stasis_app_recording_options::name, OBJ_KEY, and stasis_app_recording::options.

Referenced by load_module().

◆ recording_mute()

static int recording_mute ( struct stasis_app_recording recording)
static

Definition at line 576 of file res_stasis_recording.c.

577{
578 return toggle_recording_mute(recording, 1);
579}
static int toggle_recording_mute(struct stasis_app_recording *recording, int desired_mute_state)

References toggle_recording_mute().

◆ recording_noop()

static int recording_noop ( struct stasis_app_recording recording)
static

Definition at line 521 of file res_stasis_recording.c.

522{
523 return 0;
524}

◆ recording_options_dtor()

static void recording_options_dtor ( void *  obj)
static

Definition at line 145 of file res_stasis_recording.c.

146{
148
150}
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object

References ast_string_field_free_memory, and options.

Referenced by stasis_app_recording_options_create().

◆ recording_pause()

static int recording_pause ( struct stasis_app_recording recording)
static

◆ recording_publish()

static void recording_publish ( struct stasis_app_recording recording,
const char *  cause 
)
static

Definition at line 218 of file res_stasis_recording.c.

219{
220 RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
222
223 ast_assert(recording != NULL);
224
225 json = stasis_app_recording_to_json(recording);
226 if (json == NULL) {
227 return;
228 }
229
230 if (!ast_strlen_zero(cause)) {
231 struct ast_json *failure_cause = ast_json_string_create(cause);
232
233 if (!failure_cause) {
234 return;
235 }
236
237 if (ast_json_object_set(json, "cause", failure_cause)) {
238 return;
239 }
240 }
241
245 if (message == NULL) {
246 return;
247 }
248
250}
struct stasis_message * ast_channel_blob_create_from_cache(const char *uniqueid, struct stasis_message_type *type, struct ast_json *blob)
Create a ast_channel_blob message, pulling channel state from the cache.
struct ast_json * ast_json_string_create(const char *value)
Construct a JSON string from value.
Definition json.c:278
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition json.c:73
int ast_json_object_set(struct ast_json *object, const char *key, struct ast_json *value)
Set a field in a JSON object.
Definition json.c:414
struct ast_json * stasis_app_recording_to_json(const struct stasis_app_recording *recording)
Construct a JSON model of a recording.
const char * stasis_app_control_get_channel_id(const struct stasis_app_control *control)
Returns the uniqueid of the channel associated with this control.
Definition control.c:1503
void stasis_app_control_publish(struct stasis_app_control *control, struct stasis_message *message)
Publish a message to the control's channel's topic.
Definition control.c:1509
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition strings.h:65
Abstract JSON element (object, array, string, int, ...).
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition utils.h:981

References ao2_cleanup, ast_assert, ast_channel_blob_create_from_cache(), ast_json_object_set(), ast_json_string_create(), ast_json_unref(), ast_strlen_zero(), stasis_app_recording::control, NULL, RAII_VAR, stasis_app_control_get_channel_id(), stasis_app_control_publish(), stasis_app_recording_snapshot_type(), and stasis_app_recording_to_json().

Referenced by recording_set_state().

◆ recording_set_state()

static void recording_set_state ( struct stasis_app_recording recording,
enum stasis_app_recording_state  state,
const char *  cause 
)
static

Definition at line 253 of file res_stasis_recording.c.

256{
257 SCOPED_AO2LOCK(lock, recording);
258 recording->state = state;
259 recording_publish(recording, cause);
260}
ast_mutex_t lock
Definition app_sla.c:337
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition lock.h:611
static void recording_publish(struct stasis_app_recording *recording, const char *cause)

References lock, recording_publish(), SCOPED_AO2LOCK, and stasis_app_recording::state.

Referenced by record_file(), and recording_fail().

◆ recording_stop()

static int recording_stop ( struct stasis_app_recording recording)
static

◆ recording_to_json()

static struct ast_json * recording_to_json ( struct stasis_message message,
const struct stasis_message_sanitizer sanitize 
)
static

Definition at line 74 of file res_stasis_recording.c.

76{
77 struct ast_channel_blob *channel_blob = stasis_message_data(message);
78 struct ast_json *blob = channel_blob->blob;
79 const char *state =
81 const char *type;
82
83 if (!strcmp(state, "recording")) {
84 type = "RecordingStarted";
85 } else if (!strcmp(state, "done") || !strcasecmp(state, "canceled")) {
86 type = "RecordingFinished";
87 } else if (!strcmp(state, "failed")) {
88 type = "RecordingFailed";
89 } else {
90 return NULL;
91 }
92
93 return ast_json_pack("{s: s, s: o?, s: O}",
94 "type", type,
96 "recording", blob);
97}
static const char type[]
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition json.c:612
struct ast_json * ast_json_timeval(const struct timeval tv, const char *zone)
Construct a timeval as JSON.
Definition json.c:670
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition json.c:283
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition json.c:407
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
const struct timeval * stasis_message_timestamp(const struct stasis_message *msg)
Get the time when a message was created.
Blob of data associated with a channel.
struct ast_json * blob

References ast_json_object_get(), ast_json_pack(), ast_json_string_get(), ast_json_timeval(), ast_channel_blob::blob, NULL, stasis_message_data(), stasis_message_timestamp(), and type.

◆ recording_unmute()

static int recording_unmute ( struct stasis_app_recording recording)
static

Definition at line 581 of file res_stasis_recording.c.

582{
583 return toggle_recording_mute(recording, 0);
584}

References toggle_recording_mute().

◆ recording_unpause()

static int recording_unpause ( struct stasis_app_recording recording)
static

◆ stasis_app_control_record()

struct stasis_app_recording * stasis_app_control_record ( struct stasis_app_control control,
struct stasis_app_recording_options options 
)

Record media from a channel.

A reference to the options object may be kept, so it MUST NOT be modified after calling this function.

On error, errno is set to indicate the failure reason.

  • EINVAL: Invalid input.
  • EEXIST: A recording with that name is in session.
  • ENOMEM: Out of memory.
Parameters
controlControl for res_stasis.
optionsRecording options.
Returns
Recording control object.
Return values
NULLon error.

Definition at line 383 of file res_stasis_recording.c.

386{
387 struct stasis_app_recording *recording;
388 char *last_slash;
389
390 errno = 0;
391
392 if (options == NULL ||
393 ast_strlen_zero(options->name) ||
394 ast_strlen_zero(options->format) ||
395 options->max_silence_seconds < 0 ||
396 options->max_duration_seconds < 0) {
397 errno = EINVAL;
398 return NULL;
399 }
400
401 ast_debug(3, "%s: Sending record(%s.%s) command\n",
403 options->format);
404
405 recording = ao2_alloc(sizeof(*recording), recording_dtor);
406 if (!recording) {
407 errno = ENOMEM;
408 return NULL;
409 }
410 recording->duration.total = -1;
411 recording->duration.energy_only = -1;
412
413 ast_asprintf(&recording->absolute_name, "%s/%s",
415
416 if (recording->absolute_name == NULL) {
417 errno = ENOMEM;
418 ao2_ref(recording, -1);
419 return NULL;
420 }
421
422 if ((last_slash = strrchr(recording->absolute_name, '/'))) {
423 *last_slash = '\0';
425 recording->absolute_name, 0777) != 0) {
426 /* errno set by ast_mkdir */
427 ao2_ref(recording, -1);
428 return NULL;
429 }
430 *last_slash = '/';
431 }
432
433 ao2_ref(options, +1);
434 recording->options = options;
435 ao2_ref(control, +1);
436 recording->control = control;
438
439 if ((recording->options->if_exists == AST_RECORD_IF_EXISTS_FAIL) &&
440 (ast_fileexists(recording->absolute_name, NULL, NULL))) {
441 ast_log(LOG_WARNING, "Recording file '%s' already exists and ifExists option is failure.\n",
442 recording->absolute_name);
443 errno = EEXIST;
444 ao2_ref(recording, -1);
445 return NULL;
446 }
447
448 {
449 RAII_VAR(struct stasis_app_recording *, old_recording, NULL,
451
453
454 old_recording = ao2_find(recordings, options->name,
456 if (old_recording) {
458 "Recording %s already in progress\n",
459 recording->options->name);
460 errno = EEXIST;
461 ao2_ref(recording, -1);
462 return NULL;
463 }
464 ao2_link(recordings, recording);
465 }
466
468
470
471 return recording;
472}
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition astmm.h:267
#define ao2_link(container, obj)
Add an object to a container.
Definition astobj2.h:1532
#define ao2_find(container, arg, flags)
Definition astobj2.h:1736
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition astobj2.h:480
@ OBJ_NOLOCK
Assume that the ao2_container is already locked.
Definition astobj2.h:1063
#define ao2_alloc(data_size, destructor_fn)
Definition astobj2.h:409
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
Definition file.c:1156
@ AST_RECORD_IF_EXISTS_FAIL
#define LOG_WARNING
int errno
const char * ast_config_AST_RECORDING_DIR
Definition options.c:157
static void recording_cleanup(void *data)
static void recording_dtor(void *obj)
static int record_file(struct stasis_app_control *control, struct ast_channel *chan, void *data)
void stasis_app_control_register_add_rule(struct stasis_app_control *control, struct stasis_app_control_rule *rule)
Registers an add channel to bridge rule.
Definition control.c:225
int stasis_app_send_command_async(struct stasis_app_control *control, stasis_app_command_cb command, void *data, command_data_destructor_fn data_destructor)
Asynchronous version of stasis_app_send_command().
Definition control.c:966
@ STASIS_APP_RECORDING_STATE_QUEUED
enum ast_record_if_exists if_exists
int ast_safe_mkdir(const char *base_path, const char *path, int mode)
Recursively create directory path, but only if it resolves within the given base_path.
Definition utils.c:2618

References stasis_app_recording::absolute_name, ao2_alloc, ao2_bump, ao2_cleanup, ao2_find, ao2_link, ao2_ref, ast_asprintf, ast_config_AST_RECORDING_DIR, ast_debug, ast_fileexists(), ast_log, AST_RECORD_IF_EXISTS_FAIL, ast_safe_mkdir(), ast_strlen_zero(), stasis_app_recording::control, stasis_app_recording::duration, stasis_app_recording::energy_only, errno, stasis_app_recording_options::if_exists, lock, LOG_WARNING, stasis_app_recording_options::name, NULL, OBJ_KEY, OBJ_NOLOCK, stasis_app_recording::options, options, RAII_VAR, record_file(), recording_cleanup(), recording_dtor(), recordings, rule_recording, SCOPED_AO2LOCK, stasis_app_control_get_channel_id(), stasis_app_control_register_add_rule(), STASIS_APP_RECORDING_STATE_QUEUED, stasis_app_send_command_async(), stasis_app_recording::state, and stasis_app_recording::total.

Referenced by ast_ari_bridges_record(), and ast_ari_channels_record().

◆ stasis_app_recording_find_by_name()

struct stasis_app_recording * stasis_app_recording_find_by_name ( const char *  name)

Finds the recording object with the given name.

Parameters
nameName of the recording object to find.
Returns
Associated stasis_app_recording object.
Return values
NULLif name not found.

Definition at line 486 of file res_stasis_recording.c.

487{
489}
static const char name[]
Definition format_mp3.c:68

References ao2_find, name, OBJ_KEY, and recordings.

Referenced by ast_ari_recordings_get_live(), and control_recording().

◆ stasis_app_recording_get_name()

const char * stasis_app_recording_get_name ( struct stasis_app_recording recording)

Gets the unique name of a recording object.

Parameters
recordingRecording control object.
Returns
recording's name.
Return values
NULLif recording ic NULL

Definition at line 480 of file res_stasis_recording.c.

482{
483 return recording->options->name;
484}

References stasis_app_recording_options::name, and stasis_app_recording::options.

◆ stasis_app_recording_get_state()

enum stasis_app_recording_state stasis_app_recording_get_state ( struct stasis_app_recording recording)

Gets the current state of a recording operation.

Parameters
recordingRecording control object.
Returns
The state of the recording object.

Definition at line 474 of file res_stasis_recording.c.

476{
477 return recording->state;
478}

References stasis_app_recording::state.

◆ stasis_app_recording_if_exists_parse()

enum ast_record_if_exists stasis_app_recording_if_exists_parse ( const char *  str)

Parse a string into the if_exists enum.

Parameters
strString to parse.
Returns
How to handle an existing file.
-1 on error.

Definition at line 195 of file res_stasis_recording.c.

197{
198 if (ast_strlen_zero(str)) {
199 /* Default value */
201 }
202
203 if (strcasecmp(str, "fail") == 0) {
205 }
206
207 if (strcasecmp(str, "overwrite") == 0) {
209 }
210
211 if (strcasecmp(str, "append") == 0) {
213 }
214
216}
const char * str
Definition app_jack.c:150
@ AST_RECORD_IF_EXISTS_APPEND
@ AST_RECORD_IF_EXISTS_OVERWRITE
@ AST_RECORD_IF_EXISTS_ERROR

References AST_RECORD_IF_EXISTS_APPEND, AST_RECORD_IF_EXISTS_ERROR, AST_RECORD_IF_EXISTS_FAIL, AST_RECORD_IF_EXISTS_OVERWRITE, ast_strlen_zero(), and str.

Referenced by ast_ari_bridges_record(), and ast_ari_channels_record().

◆ stasis_app_recording_operation()

enum stasis_app_recording_oper_results stasis_app_recording_operation ( struct stasis_app_recording recording,
enum stasis_app_recording_media_operation  operation 
)

Controls the media for a given recording operation.

Parameters
recordingRecording control object.
operationMedia control operation.
Return values
STASIS_APP_RECORDING_OPER_OKon success.
Returns
stasis_app_recording_oper_results indicating failure.

Definition at line 603 of file res_stasis_recording.c.

606{
608 SCOPED_AO2LOCK(lock, recording);
609
610 if ((unsigned int)recording->state >= STASIS_APP_RECORDING_STATE_MAX) {
611 ast_log(LOG_WARNING, "Invalid recording state %u\n",
612 recording->state);
613 return -1;
614 }
615
616 if ((unsigned int)operation >= STASIS_APP_RECORDING_OPER_MAX) {
617 ast_log(LOG_WARNING, "Invalid recording operation %u\n",
618 operation);
619 return -1;
620 }
621
622 cb = operations[recording->state][operation];
623
624 if (!cb) {
626 /* So we can be specific in our error message. */
628 } else {
629 /* And, really, all operations should be valid during
630 * recording */
632 "Unhandled operation during recording: %u\n",
633 operation);
635 }
636 }
637
638 return cb(recording) ?
640}
int(* recording_operation_cb)(struct stasis_app_recording *recording)
recording_operation_cb operations[STASIS_APP_RECORDING_STATE_MAX][STASIS_APP_RECORDING_OPER_MAX]
@ STASIS_APP_RECORDING_OPER_NOT_RECORDING
@ STASIS_APP_RECORDING_OPER_FAILED
@ STASIS_APP_RECORDING_OPER_OK
@ STASIS_APP_RECORDING_STATE_MAX
@ STASIS_APP_RECORDING_OPER_MAX

References ast_log, lock, LOG_ERROR, LOG_WARNING, operations, SCOPED_AO2LOCK, STASIS_APP_RECORDING_OPER_FAILED, STASIS_APP_RECORDING_OPER_MAX, STASIS_APP_RECORDING_OPER_NOT_RECORDING, STASIS_APP_RECORDING_OPER_OK, STASIS_APP_RECORDING_STATE_MAX, STASIS_APP_RECORDING_STATE_RECORDING, and stasis_app_recording::state.

Referenced by control_recording().

◆ stasis_app_recording_options_create()

struct stasis_app_recording_options * stasis_app_recording_options_create ( const char *  name,
const char *  format 
)

Allocate a recording options object.

Clean up with ao2_cleanup().

Parameters
nameName of the recording.
formatFormat to record in.
Returns
Newly allocated options object.
Return values
NULLon error.

Definition at line 152 of file res_stasis_recording.c.

154{
157
159
160 if (!options || ast_string_field_init(options, 128)) {
161 return NULL;
162 }
164 ast_string_field_set(options, format, format);
165
166 ao2_ref(options, +1);
167 return options;
168}
static void recording_options_dtor(void *obj)
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.

References ao2_alloc, ao2_cleanup, ao2_ref, ast_string_field_init, ast_string_field_set, stasis_app_recording_options::format, name, NULL, options, RAII_VAR, and recording_options_dtor().

Referenced by ast_ari_bridges_record(), and ast_ari_channels_record().

◆ stasis_app_recording_termination_parse()

char stasis_app_recording_termination_parse ( const char *  str)

Parse a string into the recording termination enum.

Parameters
strString to parse.
Returns
DTMF value to terminate on.
Return values
STASIS_APP_RECORDING_TERMINATE_NONEto not terminate on DTMF.
STASIS_APP_RECORDING_TERMINATE_ANYto terminate on any DTMF.
STASIS_APP_RECORDING_TERMINATE_INVALIDif input was invalid.

Definition at line 170 of file res_stasis_recording.c.

171{
172 if (ast_strlen_zero(str)) {
174 }
175
176 if (strcasecmp(str, "none") == 0) {
178 }
179
180 if (strcasecmp(str, "any") == 0) {
182 }
183
184 if (strcasecmp(str, "#") == 0) {
185 return '#';
186 }
187
188 if (strcasecmp(str, "*") == 0) {
189 return '*';
190 }
191
193}

References ast_strlen_zero(), STASIS_APP_RECORDING_TERMINATE_ANY, STASIS_APP_RECORDING_TERMINATE_INVALID, STASIS_APP_RECORDING_TERMINATE_NONE, and str.

Referenced by ast_ari_bridges_record(), and ast_ari_channels_record().

◆ stasis_app_recording_to_json()

struct ast_json * stasis_app_recording_to_json ( const struct stasis_app_recording recording)

Construct a JSON model of a recording.

Parameters
recordingRecording to conver.
Returns
JSON model.
Return values
NULLon error.

Definition at line 491 of file res_stasis_recording.c.

493{
494 RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
495
496 if (recording == NULL) {
497 return NULL;
498 }
499
500 json = ast_json_pack("{s: s, s: s, s: s, s: s}",
501 "name", recording->options->name,
502 "format", recording->options->format,
503 "state", state_to_string(recording->state),
504 "target_uri", recording->options->target);
505 if (json && recording->duration.total > -1) {
506 ast_json_object_set(json, "duration",
508 }
509 if (json && recording->duration.energy_only > -1) {
510 ast_json_object_set(json, "talking_duration",
512 ast_json_object_set(json, "silence_duration",
514 }
515
516 return ast_json_ref(json);
517}
struct ast_json * ast_json_integer_create(intmax_t value)
Create a JSON integer.
Definition json.c:327
struct ast_json * ast_json_ref(struct ast_json *value)
Increase refcount on value.
Definition json.c:67
static const char * state_to_string(enum stasis_app_recording_state state)

References ast_json_integer_create(), ast_json_object_set(), ast_json_pack(), ast_json_ref(), ast_json_unref(), stasis_app_recording::duration, stasis_app_recording::energy_only, stasis_app_recording_options::format, stasis_app_recording_options::name, NULL, stasis_app_recording::options, RAII_VAR, stasis_app_recording::state, state_to_string(), stasis_app_recording_options::target, and stasis_app_recording::total.

Referenced by ast_ari_bridges_record(), ast_ari_channels_record(), ast_ari_recordings_get_live(), and recording_publish().

◆ STASIS_MESSAGE_TYPE_DEFN()

STASIS_MESSAGE_TYPE_DEFN ( stasis_app_recording_snapshot_type  ,
to_json = recording_to_json 
)

◆ state_to_string()

static const char * state_to_string ( enum stasis_app_recording_state  state)
static

◆ toggle_recording_mute()

static int toggle_recording_mute ( struct stasis_app_recording recording,
int  desired_mute_state 
)
static

Definition at line 563 of file res_stasis_recording.c.

564{
565 if (recording->muted == desired_mute_state) {
566 /* already in desired state */
567 return 0;
568 }
569
570 recording->muted = desired_mute_state;
571
574}
@ AST_CONTROL_RECORD_MUTE

References AST_CONTROL_RECORD_MUTE, stasis_app_recording::control, stasis_app_recording::muted, and stasis_app_control_queue_control().

Referenced by recording_mute(), and recording_unmute().

◆ unload_module()

static int unload_module ( void  )
static

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Stasis application recording support" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .requires = "res_stasis", .load_pri = AST_MODPRI_APP_DEPEND }
static

Definition at line 674 of file res_stasis_recording.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 674 of file res_stasis_recording.c.

◆ operations

Definition at line 586 of file res_stasis_recording.c.

586 {
601};
static int recording_unpause(struct stasis_app_recording *recording)
static int recording_pause(struct stasis_app_recording *recording)
static int recording_noop(struct stasis_app_recording *recording)
static int recording_disregard(struct stasis_app_recording *recording)
static int recording_mute(struct stasis_app_recording *recording)
static int recording_unmute(struct stasis_app_recording *recording)
static int recording_stop(struct stasis_app_recording *recording)
static int recording_cancel(struct stasis_app_recording *recording)
@ STASIS_APP_RECORDING_PAUSE
@ STASIS_APP_RECORDING_UNPAUSE
@ STASIS_APP_RECORDING_UNMUTE
@ STASIS_APP_RECORDING_STOP
@ STASIS_APP_RECORDING_MUTE
@ STASIS_APP_RECORDING_CANCEL

Referenced by stasis_app_recording_operation().

◆ recordings

struct ao2_container* recordings
static

Container of all current recordings

Definition at line 52 of file res_stasis_recording.c.

Referenced by load_module(), recording_cleanup(), stasis_app_control_record(), stasis_app_recording_find_by_name(), and unload_module().

◆ rule_recording

struct stasis_app_control_rule rule_recording
static
Initial value:
= {
.check_rule = check_rule_recording
}
static enum stasis_app_control_channel_result check_rule_recording(const struct stasis_app_control *control)

Definition at line 274 of file res_stasis_recording.c.

274 {
275 .check_rule = check_rule_recording
276};

Referenced by record_file(), recording_fail(), and stasis_app_control_record().