Asterisk - The Open Source Telephony Project  18.5.0
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. 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 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

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

Referenced by load_module().

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

References STASIS_APP_CHANNEL_RECORDING.

◆ load_module()

static int load_module ( void  )
static

Definition at line 629 of file res_stasis_recording.c.

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(), stasis_app_recording_snapshot_type(), STASIS_MESSAGE_TYPE_CLEANUP, and STASIS_MESSAGE_TYPE_INIT.

Referenced by unload_module().

630 {
631  int r;
632 
634  if (r != 0) {
636  }
637 
640  if (!recordings) {
643  }
645 }
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
Definition: stasis.h:1501
#define RECORDING_BUCKETS
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
Definition: stasis.h:1523
static int recording_cmp(void *obj, void *arg, int flags)
#define NULL
Definition: resample.c:96
static int recording_hash(const void *obj, int flags)
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Definition: astobj2.h:1310
struct stasis_message_type * stasis_app_recording_snapshot_type(void)
Message type for recording updates. The data is an ast_channel_blob.
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static struct ao2_container * recordings

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

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::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(), 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().

298 {
299  struct stasis_app_recording *recording = data;
300  char *acceptdtmf;
301  int res;
302 
303  ast_assert(recording != NULL);
304 
305  if (stasis_app_get_bridge(control)) {
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",
328  ast_channel_uniqueid(chan));
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 }
struct ast_bridge * stasis_app_get_bridge(struct stasis_app_control *control)
Gets the bridge currently associated with a control object.
Definition: control.c:931
int ast_auto_answer(struct ast_channel *chan)
Answer a channel, if it's not already answered.
Definition: channel.c:2820
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
static struct stasis_app_control_rule rule_recording
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define STASIS_APP_RECORDING_TERMINATE_ANY
#define STASIS_APP_RECORDING_TERMINATE_INVALID
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:1992
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
const char * ast_channel_uniqueid(const struct ast_channel *chan)
struct stasis_app_recording_options * options
#define LOG_ERROR
Definition: logger.h:285
struct stasis_app_recording::@498 duration
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:224
static void recording_set_state(struct stasis_app_recording *recording, enum stasis_app_recording_state state, const char *cause)
static void recording_fail(struct stasis_app_control *control, struct stasis_app_recording *recording, const char *cause)
enum ast_record_if_exists if_exists
#define STASIS_APP_RECORDING_TERMINATE_NONE

◆ recording_cancel()

static int recording_cancel ( struct stasis_app_recording recording)
static

Definition at line 519 of file res_stasis_recording.c.

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.

520 {
521  int res = 0;
523  res |= stasis_app_control_queue_control(recording->control,
525  res |= ast_filedelete(recording->absolute_name, NULL);
526  return res;
527 }
enum stasis_app_recording_state state
struct stasis_app_control * control
#define NULL
Definition: resample.c:96
int ast_filedelete(const char *filename, const char *fmt)
Deletes a file.
Definition: file.c:1098
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:1445

◆ recording_cleanup()

static void recording_cleanup ( void *  data)
static

Definition at line 287 of file res_stasis_recording.c.

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

Referenced by stasis_app_control_record().

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:1154
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_unlink_flags(container, obj, flags)
Definition: astobj2.h:1622
static struct ao2_container * recordings

◆ recording_cmp()

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

Definition at line 109 of file res_stasis_recording.c.

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

Referenced by load_module().

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 }
#define OBJ_KEY
Definition: astobj2.h:1155
struct stasis_app_recording_options * options

◆ recording_disregard()

static int recording_disregard ( struct stasis_app_recording recording)
static

Definition at line 513 of file res_stasis_recording.c.

References STASIS_APP_RECORDING_STATE_CANCELED, and stasis_app_recording::state.

514 {
516  return 0;
517 }
enum stasis_app_recording_state state

◆ recording_dtor()

static void recording_dtor ( void *  obj)
static

Definition at line 361 of file res_stasis_recording.c.

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().

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 }
struct stasis_app_control * control
struct stasis_app_recording_options * options
#define ast_free(a)
Definition: astmm.h:182
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ recording_fail()

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

Definition at line 277 of file res_stasis_recording.c.

References recording_set_state(), stasis_app_control_unregister_add_rule(), and STASIS_APP_RECORDING_STATE_FAILED.

Referenced by record_file().

280 {
282 
284  recording, STASIS_APP_RECORDING_STATE_FAILED, cause);
285 }
static struct stasis_app_control_rule rule_recording
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:224
static void recording_set_state(struct stasis_app_recording *recording, enum stasis_app_recording_state state, const char *cause)

◆ recording_hash()

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

Definition at line 102 of file res_stasis_recording.c.

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

Referenced by load_module().

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 }
#define OBJ_KEY
Definition: astobj2.h:1155
struct stasis_app_recording_options * options
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
Definition: strings.h:1206

◆ recording_mute()

static int recording_mute ( struct stasis_app_recording recording)
static

Definition at line 550 of file res_stasis_recording.c.

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

551 {
552  if (recording->muted) {
553  /* already muted */
554  return 0;
555  }
556 
557  recording->muted = 1;
558  return stasis_app_control_queue_control(recording->control,
560 }
struct stasis_app_control * control
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:1445

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

References ast_string_field_free_memory, and stasis_app_recording::options.

Referenced by stasis_app_recording_options_create().

145 {
147 
149 }
static struct test_options options
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368

◆ recording_pause()

static int recording_pause ( struct stasis_app_recording recording)
static

Definition at line 536 of file res_stasis_recording.c.

References AST_CONTROL_RECORD_SUSPEND, stasis_app_recording::control, stasis_app_control_queue_control(), STASIS_APP_RECORDING_STATE_PAUSED, and stasis_app_recording::state.

537 {
539  return stasis_app_control_queue_control(recording->control,
541 }
enum stasis_app_recording_state state
struct stasis_app_control * control
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:1445

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

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().

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 }
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:1436
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
struct stasis_app_control * control
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
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:404
#define ast_strlen_zero(foo)
Definition: strings.h:52
#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:911
struct ast_json * ast_json_string_create(const char *value)
Construct a JSON string from value.
Definition: json.c:268
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:1430
struct stasis_message_type * stasis_app_recording_snapshot_type(void)
Message type for recording updates. The data is an ast_channel_blob.
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 * stasis_app_recording_to_json(const struct stasis_app_recording *recording)
Construct a JSON model of a recording.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
Abstract JSON element (object, array, string, int, ...).

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

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

Referenced by record_file(), and recording_fail().

255 {
256  SCOPED_AO2LOCK(lock, recording);
257  recording->state = state;
258  recording_publish(recording, cause);
259 }
enum sip_cc_notify_state state
Definition: chan_sip.c:959
enum stasis_app_recording_state state
ast_mutex_t lock
Definition: app_meetme.c:1091
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:602
static void recording_publish(struct stasis_app_recording *recording, const char *cause)

◆ recording_stop()

static int recording_stop ( struct stasis_app_recording recording)
static

Definition at line 529 of file res_stasis_recording.c.

References AST_CONTROL_RECORD_STOP, stasis_app_recording::control, stasis_app_control_queue_control(), STASIS_APP_RECORDING_STATE_COMPLETE, and stasis_app_recording::state.

530 {
532  return stasis_app_control_queue_control(recording->control,
534 }
enum stasis_app_recording_state state
struct stasis_app_control * control
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:1445

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

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

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,
94  "timestamp", ast_json_timeval(*stasis_message_timestamp(message), NULL),
95  "recording", blob);
96 }
static const char type[]
Definition: chan_ooh323.c:109
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
struct ast_json * blob
#define NULL
Definition: resample.c:96
Blob of data associated with a channel.
const struct timeval * stasis_message_timestamp(const struct stasis_message *msg)
Get the time when a message was created.
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition: json.c:273
struct ast_json * ast_json_timeval(const struct timeval tv, const char *zone)
Construct a timeval as JSON.
Definition: json.c:649
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition: json.c:397
Abstract JSON element (object, array, string, int, ...).

◆ recording_unmute()

static int recording_unmute ( struct stasis_app_recording recording)
static

Definition at line 562 of file res_stasis_recording.c.

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

563 {
564  if (!recording->muted) {
565  /* already unmuted */
566  return 0;
567  }
568 
569  return stasis_app_control_queue_control(recording->control,
571 }
struct stasis_app_control * control
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:1445

◆ recording_unpause()

static int recording_unpause ( struct stasis_app_recording recording)
static

Definition at line 543 of file res_stasis_recording.c.

References AST_CONTROL_RECORD_SUSPEND, stasis_app_recording::control, stasis_app_control_queue_control(), STASIS_APP_RECORDING_STATE_RECORDING, and stasis_app_recording::state.

544 {
546  return stasis_app_control_queue_control(recording->control,
548 }
enum stasis_app_recording_state state
struct stasis_app_control * control
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:1445

◆ 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.
NULL on error.

Definition at line 370 of file res_stasis_recording.c.

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::format, stasis_app_recording_options::if_exists, lock, LOG_WARNING, stasis_app_recording_options::max_duration_seconds, stasis_app_recording_options::max_silence_seconds, stasis_app_recording_options::name, NULL, OBJ_KEY, OBJ_NOLOCK, stasis_app_recording::options, RAII_VAR, record_file(), recording_cleanup(), recording_dtor(), 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",
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,
437  ao2_cleanup);
438 
440 
441  old_recording = ao2_find(recordings, options->name,
442  OBJ_KEY | OBJ_NOLOCK);
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 }
enum stasis_app_recording_state state
#define OBJ_KEY
Definition: astobj2.h:1155
struct stasis_app_control * control
#define LOG_WARNING
Definition: logger.h:274
Assume that the ao2_container is already locked.
Definition: astobj2.h:1067
#define NULL
Definition: resample.c:96
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:269
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ao2_bump(obj)
Definition: astobj2.h:491
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:217
static struct stasis_app_control_rule rule_recording
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#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:911
ast_mutex_t lock
Definition: app_meetme.c:1091
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static void recording_dtor(void *obj)
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:904
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:1430
int errno
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:602
struct stasis_app_recording::@498 duration
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: main/utils.c:2336
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
static int record_file(struct stasis_app_control *control, struct ast_channel *chan, void *data)
const char * ast_config_AST_RECORDING_DIR
Definition: options.c:156
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
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:1086
static void recording_cleanup(void *data)
static struct test_options options
static struct ao2_container * recordings
#define ao2_link(container, obj)
Definition: astobj2.h:1549

◆ 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.
NULL if name not found.

Definition at line 473 of file res_stasis_recording.c.

References ao2_find, and OBJ_KEY.

Referenced by ast_ari_recordings_get_live(), and control_recording().

474 {
475  return ao2_find(recordings, name, OBJ_KEY);
476 }
#define OBJ_KEY
Definition: astobj2.h:1155
static const char name[]
Definition: cdr_mysql.c:74
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
static struct ao2_container * recordings

◆ 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.
NULL if 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

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

References stasis_app_recording::state.

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

References AST_RECORD_IF_EXISTS_APPEND, AST_RECORD_IF_EXISTS_ERROR, AST_RECORD_IF_EXISTS_FAIL, AST_RECORD_IF_EXISTS_OVERWRITE, and ast_strlen_zero.

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 }
const char * str
Definition: app_jack.c:147
#define ast_strlen_zero(foo)
Definition: strings.h:52

◆ 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.
controlMedia control operation.
Returns
STASIS_APP_RECORDING_OPER_OK on success.
stasis_app_recording_oper_results indicating failure.

Definition at line 590 of file res_stasis_recording.c.

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().

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) {
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 */
619  "Unhandled operation during recording: %u\n",
620  operation);
622  }
623  }
624 
625  return cb(recording) ?
627 }
enum stasis_app_recording_state state
#define LOG_WARNING
Definition: logger.h:274
recording_operation_cb operations[STASIS_APP_RECORDING_STATE_MAX][STASIS_APP_RECORDING_OPER_MAX]
#define ast_log
Definition: astobj2.c:42
int(* recording_operation_cb)(struct stasis_app_recording *recording)
ast_mutex_t lock
Definition: app_meetme.c:1091
#define LOG_ERROR
Definition: logger.h:285
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:602

◆ 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.
NULL on error.

Definition at line 151 of file res_stasis_recording.c.

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

Referenced by ast_ari_bridges_record(), and ast_ari_channels_record().

153 {
155  ao2_cleanup);
156 
158 
159  if (!options || ast_string_field_init(options, 128)) {
160  return NULL;
161  }
164 
165  ao2_ref(options, +1);
166  return options;
167 }
#define NULL
Definition: resample.c:96
#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:911
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static void recording_options_dtor(void *obj)
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
static const char name[]
Definition: cdr_mysql.c:74
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static struct test_options options
static snd_pcm_format_t format
Definition: chan_alsa.c:102
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ 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.
STASIS_APP_RECORDING_TERMINATE_NONE to not terminate on DTMF.
STASIS_APP_RECORDING_TERMINATE_ANY to terminate on any DTMF.
STASIS_APP_RECORDING_TERMINATE_INVALID if input was invalid.

Definition at line 169 of file res_stasis_recording.c.

References ast_strlen_zero, STASIS_APP_RECORDING_TERMINATE_ANY, STASIS_APP_RECORDING_TERMINATE_INVALID, and STASIS_APP_RECORDING_TERMINATE_NONE.

Referenced by ast_ari_bridges_record(), and ast_ari_channels_record().

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 }
const char * str
Definition: app_jack.c:147
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define STASIS_APP_RECORDING_TERMINATE_ANY
#define STASIS_APP_RECORDING_TERMINATE_INVALID
#define STASIS_APP_RECORDING_TERMINATE_NONE

◆ 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.
NULL on 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, 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().

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 }
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:591
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
#define NULL
Definition: resample.c:96
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:404
#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:911
struct stasis_app_recording_options * options
struct stasis_app_recording::@498 duration
Abstract JSON element (object, array, string, int, ...).
static const char * state_to_string(enum stasis_app_recording_state state)
struct ast_json * ast_json_integer_create(intmax_t value)
Create a JSON integer.
Definition: json.c:317

◆ STASIS_MESSAGE_TYPE_DEFN()

STASIS_MESSAGE_TYPE_DEFN ( stasis_app_recording_snapshot_type  ,
to_json = recording_to_json 
)

Referenced by recording_to_json().

◆ state_to_string()

static const char* state_to_string ( enum stasis_app_recording_state  state)
static

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 647 of file res_stasis_recording.c.

References ao2_cleanup, AST_MODFLAG_GLOBAL_SYMBOLS, AST_MODFLAG_LOAD_ORDER, AST_MODPRI_APP_DEPEND, AST_MODULE_INFO(), AST_MODULE_SUPPORT_CORE, ASTERISK_GPL_KEY, load_module(), NULL, stasis_app_recording_snapshot_type(), and STASIS_MESSAGE_TYPE_CLEANUP.

648 {
650  recordings = NULL;
652  return 0;
653 }
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
Definition: stasis.h:1523
#define NULL
Definition: resample.c:96
struct stasis_message_type * stasis_app_recording_snapshot_type(void)
Message type for recording updates. The data is an ast_channel_blob.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static struct ao2_container * recordings

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 = "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

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.

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.

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