Asterisk - The Open Source Telephony Project  21.4.1
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"

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. More...
 
struct stasis_app_recordingstasis_app_recording_find_by_name (const char *name)
 Finds the recording object with the given name. More...
 
const char * stasis_app_recording_get_name (struct stasis_app_recording *recording)
 Gets the unique name of a recording object. More...
 
enum stasis_app_recording_state stasis_app_recording_get_state (struct stasis_app_recording *recording)
 Gets the current state of a recording operation. More...
 
enum ast_record_if_exists stasis_app_recording_if_exists_parse (const char *str)
 Parse a string into the if_exists enum. More...
 
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. More...
 
struct stasis_app_recording_optionsstasis_app_recording_options_create (const char *name, const char *format)
 Allocate a recording options object. More...
 
char stasis_app_recording_termination_parse (const char *str)
 Parse a string into the recording termination enum. More...
 
struct ast_jsonstasis_app_recording_to_json (const struct stasis_app_recording *recording)
 Construct a JSON model of a recording. More...
 
 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 = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .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

#define RECORDING_BUCKETS   127

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

Definition at line 42 of file res_stasis_recording.c.

#define RECORDING_CHECK   0

Recording check is unimplemented. le sigh

Definition at line 48 of file res_stasis_recording.c.

#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.

Function Documentation

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.

References stasis_app_recording::absolute_name, ao2_bump, ao2_link, ao2_ref, ast_asprintf, ast_debug, ast_fileexists(), AST_RECORD_IF_EXISTS_FAIL, ast_safe_mkdir(), stasis_app_recording::control, stasis_app_recording::duration, stasis_app_recording::energy_only, stasis_app_recording_options::format, stasis_app_recording_options::if_exists, lock, stasis_app_recording_options::max_duration_seconds, stasis_app_recording_options::max_silence_seconds, stasis_app_recording_options::name, OBJ_KEY, OBJ_NOLOCK, stasis_app_recording::options, RAII_VAR, 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().

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",
389  stasis_app_control_get_channel_id(control), options->name,
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",
401  ast_config_AST_RECORDING_DIR, options->name);
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';
411  if (ast_safe_mkdir(ast_config_AST_RECORDING_DIR,
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,
437  ao2_cleanup);
438 
440 
441  old_recording = ao2_find(recordings, options->name,
442  OBJ_KEY | OBJ_NOLOCK);
443  if (old_recording) {
444  ast_log(LOG_WARNING,
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 
454  stasis_app_control_register_add_rule(control, &rule_recording);
455 
456  stasis_app_send_command_async(control, record_file, ao2_bump(recording), recording_cleanup);
457 
458  return recording;
459 }
struct stasis_app_recording::@488 duration
enum stasis_app_recording_state state
#define OBJ_KEY
Definition: astobj2.h:1151
struct stasis_app_control * control
Assume that the ao2_container is already locked.
Definition: astobj2.h:1063
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:267
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
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:232
ast_mutex_t lock
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
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:926
#define ast_debug(level,...)
Log a DEBUG message.
struct stasis_app_recording_options * options
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:1452
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:604
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:2584
enum ast_record_if_exists if_exists
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
Definition: file.c:1129
#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:941
static struct ao2_container * recordings
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
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.

References OBJ_KEY.

Referenced by ast_ari_recordings_get_live().

474 {
475  return ao2_find(recordings, name, OBJ_KEY);
476 }
#define OBJ_KEY
Definition: astobj2.h:1151
static struct ao2_container * recordings
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.

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

469 {
470  return recording->options->name;
471 }
struct stasis_app_recording_options * options
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.

References stasis_app_recording::state.

463 {
464  return recording->state;
465 }
enum stasis_app_recording_state state
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.

References AST_RECORD_IF_EXISTS_APPEND, AST_RECORD_IF_EXISTS_ERROR, AST_RECORD_IF_EXISTS_FAIL, and AST_RECORD_IF_EXISTS_OVERWRITE.

Referenced by ast_ari_bridges_record(), and ast_ari_channels_record().

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 }
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.

References lock, 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.

593 {
594  recording_operation_cb cb;
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) {
612  if (recording->state != STASIS_APP_RECORDING_STATE_RECORDING) {
613  /* So we can be specific in our error message. */
615  } else {
616  /* And, really, all operations should be valid during
617  * recording */
618  ast_log(LOG_ERROR,
619  "Unhandled operation during recording: %u\n",
620  operation);
622  }
623  }
624 
625  return cb(recording) ?
627 }
enum stasis_app_recording_state state
playback_operation_cb operations[STASIS_PLAYBACK_STATE_MAX][STASIS_PLAYBACK_MEDIA_OP_MAX]
A sparse array detailing how commands should be handled in the various playback states. Unset entries imply invalid operations.
ast_mutex_t lock
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:604
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.

References ao2_ref, ast_string_field_init, ast_string_field_set, and RAII_VAR.

Referenced by ast_ari_bridges_record(), and ast_ari_channels_record().

153 {
155  ao2_cleanup);
156 
157  options = ao2_alloc(sizeof(*options), recording_options_dtor);
158 
159  if (!options || ast_string_field_init(options, 128)) {
160  return NULL;
161  }
162  ast_string_field_set(options, name, name);
163  ast_string_field_set(options, format, format);
164 
165  ao2_ref(options, +1);
166  return options;
167 }
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
struct stasis_app_recording_options * options
#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:941
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521
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.

Referenced by ast_ari_bridges_record(), and ast_ari_channels_record().

170 {
171  if (ast_strlen_zero(str)) {
172  return STASIS_APP_RECORDING_TERMINATE_NONE;
173  }
174 
175  if (strcasecmp(str, "none") == 0) {
176  return STASIS_APP_RECORDING_TERMINATE_NONE;
177  }
178 
179  if (strcasecmp(str, "any") == 0) {
180  return STASIS_APP_RECORDING_TERMINATE_ANY;
181  }
182 
183  if (strcasecmp(str, "#") == 0) {
184  return '#';
185  }
186 
187  if (strcasecmp(str, "*") == 0) {
188  return '*';
189  }
190 
191  return STASIS_APP_RECORDING_TERMINATE_INVALID;
192 }
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.

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, stasis_app_recording::options, RAII_VAR, stasis_app_recording::state, stasis_app_recording_options::target, and stasis_app_recording::total.

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

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",
500  ast_json_integer_create(recording->duration.total - recording->duration.energy_only));
501  }
502 
503  return ast_json_ref(json);
504 }
struct stasis_app_recording::@488 duration
enum stasis_app_recording_state state
struct ast_json * ast_json_ref(struct ast_json *value)
Increase refcount on value.
Definition: json.c:67
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:612
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 stasis_app_recording_options * options
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:941
struct ast_json * ast_json_integer_create(intmax_t value)
Create a JSON integer.
Definition: json.c:327

Variable Documentation

struct ao2_container* recordings
static

Container of all current recordings

Definition at line 51 of file res_stasis_recording.c.

struct stasis_app_control_rule rule_recording
static
Initial value:
= {
.check_rule = check_rule_recording
}

Definition at line 273 of file res_stasis_recording.c.