Asterisk - The Open Source Telephony Project GIT-master-f36a736
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 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

◆ 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:780

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:2830
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:940
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:226
#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
enum ast_record_if_exists if_exists
struct stasis_app_recording::@480 duration
struct stasis_app_recording_options * options
struct stasis_app_control * control
#define ast_assert(a)
Definition: utils.h:739

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:1141
@ 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:1454
@ 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
Definition: stringfields.h:374
static struct test_options options

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:1439
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:1445
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:941

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:331
enum cc_state state
Definition: ccss.c:393
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:604
static void recording_publish(struct stasis_app_recording *recording, const char *cause)

References lock, recording_publish(), SCOPED_AO2LOCK, state, 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[]
Definition: chan_ooh323.c:109
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:1129
@ AST_RECORD_IF_EXISTS_FAIL
#define LOG_WARNING
int errno
const char * ast_config_AST_RECORDING_DIR
Definition: options.c:156
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:219
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:913
@ STASIS_APP_RECORDING_STATE_QUEUED
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

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:147
@ 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.
Definition: stringfields.h:521
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359

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

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.

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