Asterisk - The Open Source Telephony Project GIT-master-b023714
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/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 42 of file res_stasis_recording.c.

◆ RECORDING_CHECK

#define RECORDING_CHECK   0

Recording check is unimplemented. le sigh

Definition at line 48 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 45 of file res_stasis_recording.c.

Typedef Documentation

◆ recording_operation_cb

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

Definition at line 506 of file res_stasis_recording.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 661 of file res_stasis_recording.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 661 of file res_stasis_recording.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 661 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 261 of file res_stasis_recording.c.

263{
265}
@ STASIS_APP_CHANNEL_RECORDING
Definition stasis_app.h:814

References STASIS_APP_CHANNEL_RECORDING.

◆ load_module()

static int load_module ( void  )
static

Definition at line 629 of file res_stasis_recording.c.

630{
631 int r;
632
634 if (r != 0) {
636 }
637
640 if (!recordings) {
643 }
645}
@ 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:1515
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
Definition stasis.h:1493
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 296 of file res_stasis_recording.c.

298{
299 struct stasis_app_recording *recording = data;
300 char *acceptdtmf;
301 int res;
302
303 ast_assert(recording != NULL);
304
306 ast_log(LOG_ERROR, "Cannot record channel while in bridge\n");
307 recording_fail(control, recording, "Cannot record channel while in bridge");
308 return -1;
309 }
310
311 switch (recording->options->terminate_on) {
314 acceptdtmf = "";
315 break;
317 acceptdtmf = "#*0123456789abcd";
318 break;
319 default:
320 acceptdtmf = ast_alloca(2);
321 acceptdtmf[0] = recording->options->terminate_on;
322 acceptdtmf[1] = '\0';
323 }
324
325 res = ast_auto_answer(chan);
326 if (res != 0) {
327 ast_debug(3, "%s: Failed to answer\n",
329 recording_fail(control, recording, "Failed to answer channel");
330 return -1;
331 }
332
336 NULL, /* playfile */
337 recording->absolute_name,
338 recording->options->max_duration_seconds,
339 recording->options->format,
340 &recording->duration.total,
341 recording->options->max_silence_seconds ? &recording->duration.energy_only : NULL,
342 recording->options->beep,
343 -1, /* silencethreshold */
344 recording->options->max_silence_seconds * 1000,
345 NULL, /* path */
346 acceptdtmf,
347 NULL, /* canceldtmf */
348 1, /* skip_confirmation_sound */
349 recording->options->if_exists);
350
351 ast_debug(3, "%s: Recording complete\n", ast_channel_uniqueid(chan));
352
355
357
358 return 0;
359}
#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
int ast_auto_answer(struct ast_channel *chan)
Answer a channel, if it's not already answered.
Definition channel.c:2784
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:2149
#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:972
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
struct stasis_app_recording::@518 duration
struct stasis_app_recording_options * options
struct stasis_app_control * control
static struct test_options options
#define ast_assert(a)
Definition utils.h:776

References stasis_app_recording::absolute_name, ast_alloca, ast_assert, ast_auto_answer(), ast_channel_uniqueid(), ast_debug, ast_log, ast_play_and_record_full(), stasis_app_recording_options::beep, stasis_app_recording::control, stasis_app_recording::duration, stasis_app_recording::energy_only, 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 519 of file res_stasis_recording.c.

520{
521 int res = 0;
525 res |= ast_filedelete(recording->absolute_name, NULL);
526 return res;
527}
int ast_filedelete(const char *filename, const char *fmt)
Deletes a file.
Definition file.c:1160
@ 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:1490
@ STASIS_APP_RECORDING_STATE_CANCELED
enum stasis_app_recording_state state

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 287 of file res_stasis_recording.c.

288{
289 struct stasis_app_recording *recording = data;
290
291 ao2_unlink_flags(recordings, recording,
293 ao2_ref(recording, -1);
294}
#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 109 of file res_stasis_recording.c.

110{
111 struct stasis_app_recording *lhs = obj;
112 struct stasis_app_recording *rhs = arg;
113 const char *rhs_id = flags & OBJ_KEY ? arg : rhs->options->name;
114
115 if (strcmp(lhs->options->name, rhs_id) == 0) {
116 return CMP_MATCH | CMP_STOP;
117 } else {
118 return 0;
119 }
120}
@ 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 513 of file res_stasis_recording.c.

514{
516 return 0;
517}

References STASIS_APP_RECORDING_STATE_CANCELED, and stasis_app_recording::state.

◆ recording_dtor()

static void recording_dtor ( void *  obj)
static

Definition at line 361 of file res_stasis_recording.c.

362{
363 struct stasis_app_recording *recording = obj;
364
365 ast_free(recording->absolute_name);
366 ao2_cleanup(recording->control);
367 ao2_cleanup(recording->options);
368}
#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 102 of file res_stasis_recording.c.

103{
104 const struct stasis_app_recording *recording = obj;
105 const char *id = flags & OBJ_KEY ? obj : recording->options->name;
106 return ast_str_hash(id);
107}
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 563 of file res_stasis_recording.c.

564{
565 return toggle_recording_mute(recording, 1);
566}
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 508 of file res_stasis_recording.c.

509{
510 return 0;
511}

◆ recording_options_dtor()

static void recording_options_dtor ( void *  obj)
static

Definition at line 144 of file res_stasis_recording.c.

145{
147
149}
#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 217 of file res_stasis_recording.c.

218{
219 RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
221
222 ast_assert(recording != NULL);
223
224 json = stasis_app_recording_to_json(recording);
225 if (json == NULL) {
226 return;
227 }
228
229 if (!ast_strlen_zero(cause)) {
230 struct ast_json *failure_cause = ast_json_string_create(cause);
231
232 if (!failure_cause) {
233 return;
234 }
235
236 if (ast_json_object_set(json, "cause", failure_cause)) {
237 return;
238 }
239 }
240
244 if (message == NULL) {
245 return;
246 }
247
249}
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:1475
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:1481
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:978

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 252 of file res_stasis_recording.c.

255{
256 SCOPED_AO2LOCK(lock, recording);
257 recording->state = state;
258 recording_publish(recording, cause);
259}
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 73 of file res_stasis_recording.c.

75{
76 struct ast_channel_blob *channel_blob = stasis_message_data(message);
77 struct ast_json *blob = channel_blob->blob;
78 const char *state =
80 const char *type;
81
82 if (!strcmp(state, "recording")) {
83 type = "RecordingStarted";
84 } else if (!strcmp(state, "done") || !strcasecmp(state, "canceled")) {
85 type = "RecordingFinished";
86 } else if (!strcmp(state, "failed")) {
87 type = "RecordingFailed";
88 } else {
89 return NULL;
90 }
91
92 return ast_json_pack("{s: s, s: o?, s: O}",
93 "type", type,
95 "recording", blob);
96}
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 568 of file res_stasis_recording.c.

569{
570 return toggle_recording_mute(recording, 0);
571}

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 370 of file res_stasis_recording.c.

373{
374 struct stasis_app_recording *recording;
375 char *last_slash;
376
377 errno = 0;
378
379 if (options == NULL ||
380 ast_strlen_zero(options->name) ||
381 ast_strlen_zero(options->format) ||
382 options->max_silence_seconds < 0 ||
383 options->max_duration_seconds < 0) {
384 errno = EINVAL;
385 return NULL;
386 }
387
388 ast_debug(3, "%s: Sending record(%s.%s) command\n",
390 options->format);
391
392 recording = ao2_alloc(sizeof(*recording), recording_dtor);
393 if (!recording) {
394 errno = ENOMEM;
395 return NULL;
396 }
397 recording->duration.total = -1;
398 recording->duration.energy_only = -1;
399
400 ast_asprintf(&recording->absolute_name, "%s/%s",
402
403 if (recording->absolute_name == NULL) {
404 errno = ENOMEM;
405 ao2_ref(recording, -1);
406 return NULL;
407 }
408
409 if ((last_slash = strrchr(recording->absolute_name, '/'))) {
410 *last_slash = '\0';
412 recording->absolute_name, 0777) != 0) {
413 /* errno set by ast_mkdir */
414 ao2_ref(recording, -1);
415 return NULL;
416 }
417 *last_slash = '/';
418 }
419
420 ao2_ref(options, +1);
421 recording->options = options;
422 ao2_ref(control, +1);
423 recording->control = control;
425
426 if ((recording->options->if_exists == AST_RECORD_IF_EXISTS_FAIL) &&
427 (ast_fileexists(recording->absolute_name, NULL, NULL))) {
428 ast_log(LOG_WARNING, "Recording file '%s' already exists and ifExists option is failure.\n",
429 recording->absolute_name);
430 errno = EEXIST;
431 ao2_ref(recording, -1);
432 return NULL;
433 }
434
435 {
436 RAII_VAR(struct stasis_app_recording *, old_recording, NULL,
438
440
441 old_recording = ao2_find(recordings, options->name,
443 if (old_recording) {
445 "Recording %s already in progress\n",
446 recording->options->name);
447 errno = EEXIST;
448 ao2_ref(recording, -1);
449 return NULL;
450 }
451 ao2_link(recordings, recording);
452 }
453
455
457
458 return recording;
459}
#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:1148
@ 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:945
@ 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:2620

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 473 of file res_stasis_recording.c.

474{
476}
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 467 of file res_stasis_recording.c.

469{
470 return recording->options->name;
471}

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 461 of file res_stasis_recording.c.

463{
464 return recording->state;
465}

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 194 of file res_stasis_recording.c.

196{
197 if (ast_strlen_zero(str)) {
198 /* Default value */
200 }
201
202 if (strcasecmp(str, "fail") == 0) {
204 }
205
206 if (strcasecmp(str, "overwrite") == 0) {
208 }
209
210 if (strcasecmp(str, "append") == 0) {
212 }
213
215}
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 590 of file res_stasis_recording.c.

593{
595 SCOPED_AO2LOCK(lock, recording);
596
597 if ((unsigned int)recording->state >= STASIS_APP_RECORDING_STATE_MAX) {
598 ast_log(LOG_WARNING, "Invalid recording state %u\n",
599 recording->state);
600 return -1;
601 }
602
603 if ((unsigned int)operation >= STASIS_APP_RECORDING_OPER_MAX) {
604 ast_log(LOG_WARNING, "Invalid recording operation %u\n",
605 operation);
606 return -1;
607 }
608
609 cb = operations[recording->state][operation];
610
611 if (!cb) {
613 /* So we can be specific in our error message. */
615 } else {
616 /* And, really, all operations should be valid during
617 * recording */
619 "Unhandled operation during recording: %u\n",
620 operation);
622 }
623 }
624
625 return cb(recording) ?
627}
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 151 of file res_stasis_recording.c.

153{
156
158
159 if (!options || ast_string_field_init(options, 128)) {
160 return NULL;
161 }
163 ast_string_field_set(options, format, format);
164
165 ao2_ref(options, +1);
166 return options;
167}
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 169 of file res_stasis_recording.c.

170{
171 if (ast_strlen_zero(str)) {
173 }
174
175 if (strcasecmp(str, "none") == 0) {
177 }
178
179 if (strcasecmp(str, "any") == 0) {
181 }
182
183 if (strcasecmp(str, "#") == 0) {
184 return '#';
185 }
186
187 if (strcasecmp(str, "*") == 0) {
188 return '*';
189 }
190
192}

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 478 of file res_stasis_recording.c.

480{
481 RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
482
483 if (recording == NULL) {
484 return NULL;
485 }
486
487 json = ast_json_pack("{s: s, s: s, s: s, s: s}",
488 "name", recording->options->name,
489 "format", recording->options->format,
490 "state", state_to_string(recording->state),
491 "target_uri", recording->options->target);
492 if (json && recording->duration.total > -1) {
493 ast_json_object_set(json, "duration",
495 }
496 if (json && recording->duration.energy_only > -1) {
497 ast_json_object_set(json, "talking_duration",
499 ast_json_object_set(json, "silence_duration",
501 }
502
503 return ast_json_ref(json);
504}
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 550 of file res_stasis_recording.c.

551{
552 if (recording->muted == desired_mute_state) {
553 /* already in desired state */
554 return 0;
555 }
556
557 recording->muted = desired_mute_state;
558
561}
@ 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 661 of file res_stasis_recording.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 661 of file res_stasis_recording.c.

◆ operations

Definition at line 573 of file res_stasis_recording.c.

573 {
588};
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 51 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 273 of file res_stasis_recording.c.

273 {
274 .check_rule = check_rule_recording
275};

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