Asterisk - The Open Source Telephony Project  21.4.1
Data Structures | Macros | Typedefs | Functions | Variables
res_stasis_playback.c File Reference

res_stasis playback support. More...

#include "asterisk.h"
#include "asterisk/app.h"
#include "asterisk/astobj2.h"
#include "asterisk/bridge.h"
#include "asterisk/bridge_internal.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/paths.h"
#include "asterisk/stasis_app_impl.h"
#include "asterisk/stasis_app_playback.h"
#include "asterisk/stasis_app_recording.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/stringfields.h"
#include "asterisk/uuid.h"
#include "asterisk/say.h"
#include "asterisk/indications.h"

Go to the source code of this file.

Data Structures

struct  stasis_app_playback
 

Macros

#define CHARACTERS_URI_SCHEME   "characters:"
 
#define DIGITS_URI_SCHEME   "digits:"
 
#define NUMBER_URI_SCHEME   "number:"
 
#define PLAYBACK_BUCKETS   127
 
#define PLAYBACK_DEFAULT_SKIPMS   3000
 
#define RECORDING_URI_SCHEME   "recording:"
 
#define SOUND_URI_SCHEME   "sound:"
 
#define TONE_URI_SCHEME   "tone:"
 

Typedefs

typedef int(* playback_operation_cb) (struct stasis_app_playback *playback)
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static int load_module (void)
 
static void play_on_channel (struct stasis_app_playback *playback, struct ast_channel *chan)
 
static void play_on_channel_in_bridge (struct ast_bridge_channel *bridge_channel, const char *playback_id)
 Special case code to play while a channel is in a bridge. More...
 
static int play_uri (struct stasis_app_control *control, struct ast_channel *chan, void *data)
 
static int playback_cancel (struct stasis_app_playback *playback)
 
static int playback_cmp (void *obj, void *arg, int flags)
 
static struct stasis_app_playbackplayback_create (struct stasis_app_control *control, const char *id)
 
static void playback_dtor (void *obj)
 
static void playback_final_update (struct stasis_app_playback *playback, long playedms, int res, int hangup, const char *uniqueid)
 
static int playback_first_update (struct stasis_app_playback *playback, const char *uniqueid)
 
static int playback_forward (struct stasis_app_playback *playback)
 
static int playback_hash (const void *obj, int flags)
 
static int playback_noop (struct stasis_app_playback *playback)
 
static int playback_pause (struct stasis_app_playback *playback)
 
static void playback_publish (struct stasis_app_playback *playback)
 
static int playback_restart (struct stasis_app_playback *playback)
 
static int playback_reverse (struct stasis_app_playback *playback)
 
static int playback_stop (struct stasis_app_playback *playback)
 
static struct ast_jsonplayback_to_json (struct stasis_message *message, const struct stasis_message_sanitizer *sanitize)
 
static int playback_unpause (struct stasis_app_playback *playback)
 
static void remove_from_playbacks (void *data)
 RAII_VAR function to remove a playback from the global list when leaving scope.
 
static void set_target_uri (struct stasis_app_playback *playback, enum stasis_app_playback_target_type target_type, const char *target_id)
 
struct stasis_app_playbackstasis_app_control_play_uri (struct stasis_app_control *control, const char **media, size_t media_count, const char *language, const char *target_id, enum stasis_app_playback_target_type target_type, int skipms, long offsetms, const char *id)
 Play a file to the control's channel. More...
 
struct stasis_app_playbackstasis_app_playback_find_by_id (const char *id)
 Finds the playback object with the given id. More...
 
const char * stasis_app_playback_get_id (struct stasis_app_playback *control)
 Gets the unique id of a playback object. More...
 
enum stasis_app_playback_state stasis_app_playback_get_state (struct stasis_app_playback *control)
 Gets the current state of a playback operation. More...
 
enum stasis_playback_oper_results stasis_app_playback_operation (struct stasis_app_playback *playback, enum stasis_app_playback_media_operation operation)
 Controls the media for a given playback operation. More...
 
struct ast_jsonstasis_app_playback_to_json (const struct stasis_app_playback *playback)
 Convert a playback to its JSON representation. More...
 
 STASIS_MESSAGE_TYPE_DEFN (stasis_app_playback_snapshot_type,.to_json=playback_to_json,)
 
static const char * state_to_string (enum stasis_app_playback_state state)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .description = "Stasis application playback 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,res_stasis_recording" }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
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.
 
static struct ao2_containerplaybacks
 

Detailed Description

res_stasis playback support.

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

Definition in file res_stasis_playback.c.

Macro Definition Documentation

#define PLAYBACK_BUCKETS   127

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

Definition at line 52 of file res_stasis_playback.c.

#define PLAYBACK_DEFAULT_SKIPMS   3000

Default number of milliseconds of media to skip

Definition at line 55 of file res_stasis_playback.c.

Referenced by stasis_app_control_play_uri().

Function Documentation

static void play_on_channel_in_bridge ( struct ast_bridge_channel bridge_channel,
const char *  playback_id 
)
static

Special case code to play while a channel is in a bridge.

Parameters
bridge_channelThe channel's bridge_channel.
playback_idId of the playback to start.

Definition at line 407 of file res_stasis_playback.c.

References ast_bridge_channel::chan, RAII_VAR, and stasis_app_playback_find_by_id().

409 {
410  RAII_VAR(struct stasis_app_playback *, playback, NULL, ao2_cleanup);
411 
412  playback = stasis_app_playback_find_by_id(playback_id);
413  if (!playback) {
414  ast_log(LOG_ERROR, "Couldn't find playback %s\n",
415  playback_id);
416  return;
417  }
418 
419  play_on_channel(playback, bridge_channel->chan);
420 }
struct stasis_app_playback * stasis_app_playback_find_by_id(const char *id)
Finds the playback object with the given id.
struct ast_channel * chan
#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 stasis_app_playback* stasis_app_control_play_uri ( struct stasis_app_control control,
const char **  media,
size_t  media_count,
const char *  language,
const char *  target_id,
enum stasis_app_playback_target_type  target_type,
int  skipms,
long  offsetms,
const char *  id 
)

Play a file to the control's channel.

Note that the file isn't the full path to the file. Asterisk's internal playback mechanism will automagically select the best format based on the available codecs for the channel.

Parameters
controlControl for res_stasis.
mediaArray of const char * media files to play.
media_countThe number of media files in media.
languageSelects the file based on language.
target_idID of the target bridge or channel.
target_typeWhat the target type is
skipmsNumber of milliseconds to skip for forward/reverse operations.
offsetmsNumber of milliseconds to skip before playing.
idID to assign the new playback or NULL for default.
Returns
Playback control object.
Return values
NULLon error.

Definition at line 488 of file res_stasis_playback.c.

References ao2_bump, ao2_link, ao2_ref, ast_debug, ast_malloc, ast_string_field_set, AST_VECTOR_APPEND, AST_VECTOR_GET, stasis_app_playback::medias, stasis_app_playback::offsetms, PLAYBACK_DEFAULT_SKIPMS, remove_from_playbacks(), stasis_app_playback::skipms, stasis_app_control_get_channel_id(), stasis_app_send_command_async(), STASIS_PLAYBACK_STATE_QUEUED, and stasis_app_playback::state.

Referenced by ari_bridges_play_helper().

493 {
494  struct stasis_app_playback *playback;
495  size_t i;
496 
497  if (skipms < 0 || offsetms < 0 || media_count == 0) {
498  return NULL;
499  }
500 
501  playback = playback_create(control, id);
502  if (!playback) {
503  return NULL;
504  }
505 
506  for (i = 0; i < media_count; i++) {
507  char *media_uri;
508 
509  if (ast_strlen_zero(media[i])) {
510  ast_log(LOG_ERROR, "Attempted to play media on channel '%s' but no media URI was provided.\n",
512  ao2_ref(playback, -1);
513  return NULL;
514  }
515 
516  media_uri = ast_malloc(strlen(media[i]) + 1);
517  if (!media_uri) {
518  ao2_ref(playback, -1);
519  return NULL;
520  }
521 
522  ast_debug(3, "%s: Sending play(%s) command\n",
524 
525  /* safe */
526  strcpy(media_uri, media[i]);
527  if (AST_VECTOR_APPEND(&playback->medias, media_uri)) {
528  ao2_ref(playback, -1);
529  ast_free(media_uri);
530  return NULL;
531  }
532  }
533 
534  if (skipms == 0) {
536  }
537 
538  ast_string_field_set(playback, media, AST_VECTOR_GET(&playback->medias, 0));
540  set_target_uri(playback, target_type, target_id);
541  playback->skipms = skipms;
542  playback->offsetms = offsetms;
543  ao2_link(playbacks, playback);
544 
546  playback_publish(playback);
547 
548  stasis_app_send_command_async(control, play_uri, ao2_bump(playback), remove_from_playbacks);
549 
550  return playback;
551 }
static struct ao2_container * playbacks
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
#define PLAYBACK_DEFAULT_SKIPMS
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
const ast_string_field media
enum stasis_app_playback_state state
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
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.
static void remove_from_playbacks(void *data)
RAII_VAR function to remove a playback from the global list when leaving scope.
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 AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:680
struct stasis_app_playback::@487 medias
const ast_string_field language
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
struct stasis_app_playback* stasis_app_playback_find_by_id ( const char *  id)

Finds the playback object with the given id.

Parameters
idId of the playback object to find.
Returns
Associated stasis_app_playback object.
Return values
NULLif id not found.

Definition at line 567 of file res_stasis_playback.c.

References OBJ_KEY.

Referenced by ast_ari_playbacks_control(), ast_ari_playbacks_get(), ast_ari_playbacks_stop(), and play_on_channel_in_bridge().

568 {
569  return ao2_find(playbacks, id, OBJ_KEY);
570 }
#define OBJ_KEY
Definition: astobj2.h:1151
static struct ao2_container * playbacks
const char* stasis_app_playback_get_id ( struct stasis_app_playback playback)

Gets the unique id of a playback object.

Parameters
playbackPlayback control object.
Returns
playback's id.
Return values
NULLif playback ic NULL

Definition at line 560 of file res_stasis_playback.c.

References stasis_app_playback::id.

Referenced by ari_bridges_play_helper().

562 {
563  /* id is immutable; no lock needed */
564  return control->id;
565 }
const ast_string_field id
enum stasis_app_playback_state stasis_app_playback_get_state ( struct stasis_app_playback playback)

Gets the current state of a playback operation.

Parameters
playbackPlayback control object.
Returns
The state of the playback object.

Definition at line 553 of file res_stasis_playback.c.

References lock, SCOPED_AO2LOCK, and stasis_app_playback::state.

555 {
556  SCOPED_AO2LOCK(lock, control);
557  return control->state;
558 }
ast_mutex_t lock
enum stasis_app_playback_state state
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:604
enum stasis_playback_oper_results stasis_app_playback_operation ( struct stasis_app_playback playback,
enum stasis_app_playback_media_operation  operation 
)

Controls the media for a given playback operation.

Parameters
playbackPlayback control object.
operationMedia control operation.
Return values
STASIS_PLAYBACK_OPER_OKon success.
Returns
stasis_playback_oper_results indicating failure.

Definition at line 726 of file res_stasis_playback.c.

References lock, SCOPED_AO2LOCK, STASIS_PLAYBACK_MEDIA_OP_MAX, STASIS_PLAYBACK_STATE_MAX, STASIS_PLAYBACK_STATE_PLAYING, and stasis_app_playback::state.

Referenced by ast_ari_playbacks_control(), and ast_ari_playbacks_stop().

729 {
730  playback_operation_cb cb;
731  SCOPED_AO2LOCK(lock, playback);
732 
733  ast_assert((unsigned int)playback->state < STASIS_PLAYBACK_STATE_MAX);
734 
735  if (operation >= STASIS_PLAYBACK_MEDIA_OP_MAX) {
736  ast_log(LOG_ERROR, "Invalid playback operation %u\n", operation);
737  return -1;
738  }
739 
740  cb = operations[playback->state][operation];
741 
742  if (!cb) {
743  if (playback->state != STASIS_PLAYBACK_STATE_PLAYING) {
744  /* So we can be specific in our error message. */
745  return STASIS_PLAYBACK_OPER_NOT_PLAYING;
746  } else {
747  /* And, really, all operations should be valid during
748  * playback */
749  ast_log(LOG_ERROR,
750  "Unhandled operation during playback: %u\n",
751  operation);
752  return STASIS_PLAYBACK_OPER_FAILED;
753  }
754  }
755 
756  return cb(playback) ?
757  STASIS_PLAYBACK_OPER_FAILED : STASIS_PLAYBACK_OPER_OK;
758 }
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
enum stasis_app_playback_state state
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:604
struct ast_json* stasis_app_playback_to_json ( const struct stasis_app_playback playback)

Convert a playback to its JSON representation.

Parameters
playbackThe playback object to convert to JSON
Return values
NULLon error
Returns
A JSON object on success

Definition at line 572 of file res_stasis_playback.c.

References ast_json_pack(), ast_json_ref(), ast_json_unref(), AST_VECTOR_GET, AST_VECTOR_SIZE, stasis_app_playback::id, stasis_app_playback::language, stasis_app_playback::media, stasis_app_playback::media_index, stasis_app_playback::medias, RAII_VAR, stasis_app_playback::state, and stasis_app_playback::target.

Referenced by ari_bridges_play_helper(), and ast_ari_playbacks_get().

574 {
575  RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
576 
577  if (playback == NULL) {
578  return NULL;
579  }
580 
581  if (playback->media_index == AST_VECTOR_SIZE(&playback->medias) - 1) {
582  json = ast_json_pack("{s: s, s: s, s: s, s: s, s: s}",
583  "id", playback->id,
584  "media_uri", playback->media,
585  "target_uri", playback->target,
586  "language", playback->language,
587  "state", state_to_string(playback->state));
588  } else {
589  json = ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: s}",
590  "id", playback->id,
591  "media_uri", playback->media,
592  "next_media_uri", AST_VECTOR_GET(&playback->medias, playback->media_index + 1),
593  "target_uri", playback->target,
594  "language", playback->language,
595  "state", state_to_string(playback->state));
596  }
597 
598  return ast_json_ref(json);
599 }
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
const ast_string_field target
const ast_string_field id
const ast_string_field media
enum stasis_app_playback_state state
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:680
struct stasis_app_playback::@487 medias
Abstract JSON element (object, array, string, int, ...).
const ast_string_field language
#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_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:609

Variable Documentation

struct ao2_container* playbacks
static

Container of all current playbacks

Definition at line 65 of file res_stasis_playback.c.