Asterisk - The Open Source Telephony Project GIT-master-5963e62
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
Data Structures | Macros | Functions | Variables
audiohook.c File Reference

Audiohooks Architecture. More...

#include "asterisk.h"
#include <signal.h>
#include "asterisk/channel.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/audiohook.h"
#include "asterisk/slinfactory.h"
#include "asterisk/frame.h"
#include "asterisk/translate.h"
#include "asterisk/format_cache.h"
#include "asterisk/test.h"
Include dependency graph for audiohook.c:

Go to the source code of this file.

Data Structures

struct  ast_audiohook_list
 
struct  ast_audiohook_translate
 
struct  audiohook_volume
 Audiohook volume adjustment structure. More...
 

Macros

#define AST_AUDIOHOOK_LONG_QUEUE_TOLERANCE   500
 
#define AST_AUDIOHOOK_SMALL_QUEUE_TOLERANCE   100
 
#define AST_AUDIOHOOK_SYNC_TOLERANCE   100
 
#define DEFAULT_INTERNAL_SAMPLE_RATE   8000
 
#define SHOULD_MUTE(hook, dir)
 

Functions

int ast_audiohook_attach (struct ast_channel *chan, struct ast_audiohook *audiohook)
 Attach audiohook to channel. More...
 
int ast_audiohook_destroy (struct ast_audiohook *audiohook)
 Destroys an audiohook structure. More...
 
int ast_audiohook_detach (struct ast_audiohook *audiohook)
 Detach audiohook from channel. More...
 
void ast_audiohook_detach_list (struct ast_audiohook_list *audiohook_list)
 Detach audiohooks from list and destroy said list. More...
 
int ast_audiohook_detach_source (struct ast_channel *chan, const char *source)
 Detach specified source audiohook from channel. More...
 
int ast_audiohook_init (struct ast_audiohook *audiohook, enum ast_audiohook_type type, const char *source, enum ast_audiohook_init_flags init_flags)
 Initialize an audiohook structure. More...
 
void ast_audiohook_move_all (struct ast_channel *old_chan, struct ast_channel *new_chan)
 Move all audiohooks from one channel to another. More...
 
void ast_audiohook_move_by_source (struct ast_channel *old_chan, struct ast_channel *new_chan, const char *source)
 Move an audiohook from one channel to a new one. More...
 
struct ast_frameast_audiohook_read_frame (struct ast_audiohook *audiohook, size_t samples, enum ast_audiohook_direction direction, struct ast_format *format)
 Reads a frame in from the audiohook structure. More...
 
struct ast_frameast_audiohook_read_frame_all (struct ast_audiohook *audiohook, size_t samples, struct ast_format *format, struct ast_frame **read_frame, struct ast_frame **write_frame)
 Reads a frame in from the audiohook structure in mixed audio mode and copies read and write frame data to provided arguments. More...
 
int ast_audiohook_remove (struct ast_channel *chan, struct ast_audiohook *audiohook)
 Remove an audiohook from a specified channel. More...
 
int ast_audiohook_set_frame_feed_direction (struct ast_audiohook *audiohook, enum ast_audiohook_direction direction)
 Sets direction on audiohook. More...
 
int ast_audiohook_set_mute (struct ast_channel *chan, const char *source, enum ast_audiohook_flags flag, int clear)
 Mute frames read from or written to a channel. More...
 
int ast_audiohook_set_mute_all (struct ast_channel *chan, const char *source, enum ast_audiohook_flags flag, int clearmute)
 Mute frames read from or written for all audiohooks on a channel. More...
 
void ast_audiohook_trigger_wait (struct ast_audiohook *audiohook)
 Wait for audiohook trigger to be triggered. More...
 
void ast_audiohook_update_status (struct ast_audiohook *audiohook, enum ast_audiohook_status status)
 Update audiohook's status. More...
 
int ast_audiohook_volume_adjust (struct ast_channel *chan, enum ast_audiohook_direction direction, int volume)
 Adjust the volume on frames read from or written to a channel. More...
 
int ast_audiohook_volume_adjust_float (struct ast_channel *chan, enum ast_audiohook_direction direction, float volume)
 Adjust the volume on frames read from or written to a channel. More...
 
int ast_audiohook_volume_get (struct ast_channel *chan, enum ast_audiohook_direction direction)
 Retrieve the volume adjustment value on frames read from or written to a channel. More...
 
float ast_audiohook_volume_get_float (struct ast_channel *chan, enum ast_audiohook_direction direction)
 Retrieve the volume adjustment value on frames read from or written to a channel. More...
 
int ast_audiohook_volume_set (struct ast_channel *chan, enum ast_audiohook_direction direction, int volume)
 Adjust the volume on frames read from or written to a channel. More...
 
int ast_audiohook_volume_set_float (struct ast_channel *chan, enum ast_audiohook_direction direction, float volume)
 Adjust the volume on frames read from or written to a channel. More...
 
int ast_audiohook_write_frame (struct ast_audiohook *audiohook, enum ast_audiohook_direction direction, struct ast_frame *frame)
 Writes a frame into the audiohook structure. More...
 
struct ast_frameast_audiohook_write_list (struct ast_channel *chan, struct ast_audiohook_list *audiohook_list, enum ast_audiohook_direction direction, struct ast_frame *frame)
 Pass a frame off to be handled by the audiohook core. More...
 
int ast_audiohook_write_list_empty (struct ast_audiohook_list *audiohook_list)
 Determine if a audiohook_list is empty or not. More...
 
int ast_channel_audiohook_count_by_source (struct ast_channel *chan, const char *source, enum ast_audiohook_type type)
 Find out how many audiohooks from a certain source exist on a given channel, regardless of status. More...
 
int ast_channel_audiohook_count_by_source_running (struct ast_channel *chan, const char *source, enum ast_audiohook_type type)
 Find out how many spies of a certain type exist on a given channel, and are in state running. More...
 
static struct ast_frameaudio_audiohook_write_list (struct ast_channel *chan, struct ast_audiohook_list *audiohook_list, enum ast_audiohook_direction direction, struct ast_frame *frame)
 Pass an AUDIO frame off to be handled by the audiohook core. More...
 
static void audiohook_list_set_hook_rate (struct ast_audiohook_list *audiohook_list, struct ast_audiohook *audiohook, int *rate)
 Set the audiohook's internal sample rate to the audiohook_list's rate, but only when native slin compatibility is turned on. More...
 
static void audiohook_list_set_samplerate_compatibility (struct ast_audiohook_list *audiohook_list)
 
static struct ast_frameaudiohook_list_translate_to_native (struct ast_audiohook_list *audiohook_list, enum ast_audiohook_direction direction, struct ast_frame *slin_frame, struct ast_format *outformat)
 
static struct ast_frameaudiohook_list_translate_to_slin (struct ast_audiohook_list *audiohook_list, enum ast_audiohook_direction direction, struct ast_frame *frame)
 
static void audiohook_move (struct ast_channel *old_chan, struct ast_channel *new_chan, struct ast_audiohook *audiohook)
 
static struct ast_frameaudiohook_read_frame_both (struct ast_audiohook *audiohook, size_t samples, struct ast_frame **read_reference, struct ast_frame **write_reference)
 
static struct ast_frameaudiohook_read_frame_helper (struct ast_audiohook *audiohook, size_t samples, enum ast_audiohook_direction direction, struct ast_format *format, struct ast_frame **read_reference, struct ast_frame **write_reference)
 
static struct ast_frameaudiohook_read_frame_single (struct ast_audiohook *audiohook, size_t samples, enum ast_audiohook_direction direction)
 
static int audiohook_set_internal_rate (struct ast_audiohook *audiohook, int rate, int reset)
 
static int audiohook_volume_callback (struct ast_audiohook *audiohook, struct ast_channel *chan, struct ast_frame *frame, enum ast_audiohook_direction direction)
 Helper function which actually gets called by audiohooks to perform the adjustment. More...
 
static void audiohook_volume_destroy (void *data)
 Callback used to destroy the audiohook volume datastore. More...
 
static struct audiohook_volumeaudiohook_volume_get (struct ast_channel *chan, int create)
 Helper function which finds and optionally creates an audiohook_volume_datastore datastore on a channel. More...
 
static struct ast_framedtmf_audiohook_write_list (struct ast_channel *chan, struct ast_audiohook_list *audiohook_list, enum ast_audiohook_direction direction, struct ast_frame *frame)
 Pass a DTMF frame off to be handled by the audiohook core. More...
 
static struct ast_audiohookfind_audiohook_by_source (struct ast_audiohook_list *audiohook_list, const char *source)
 find an audiohook based on its source More...
 

Variables

static const struct ast_datastore_info audiohook_volume_datastore
 Datastore used to store audiohook volume information. More...
 

Detailed Description

Audiohooks Architecture.

Author
Joshua Colp jcolp.nosp@m.@dig.nosp@m.ium.c.nosp@m.om

Definition in file audiohook.c.

Macro Definition Documentation

◆ AST_AUDIOHOOK_LONG_QUEUE_TOLERANCE

#define AST_AUDIOHOOK_LONG_QUEUE_TOLERANCE   500

Otheriwise we still don't want the queue to grow indefinitely

Definition at line 46 of file audiohook.c.

◆ AST_AUDIOHOOK_SMALL_QUEUE_TOLERANCE

#define AST_AUDIOHOOK_SMALL_QUEUE_TOLERANCE   100

When small queue is enabled, this is the maximum amount of audio that can remain queued at a time.

Definition at line 45 of file audiohook.c.

◆ AST_AUDIOHOOK_SYNC_TOLERANCE

#define AST_AUDIOHOOK_SYNC_TOLERANCE   100

Tolerance in milliseconds for audiohooks synchronization

Definition at line 44 of file audiohook.c.

◆ DEFAULT_INTERNAL_SAMPLE_RATE

#define DEFAULT_INTERNAL_SAMPLE_RATE   8000

Definition at line 48 of file audiohook.c.

◆ SHOULD_MUTE

#define SHOULD_MUTE (   hook,
  dir 
)
Value:
@ AST_AUDIOHOOK_DIRECTION_READ
Definition: audiohook.h:49
@ AST_AUDIOHOOK_DIRECTION_WRITE
Definition: audiohook.h:50
@ AST_AUDIOHOOK_MUTE_READ
Definition: audiohook.h:64
@ AST_AUDIOHOOK_MUTE_WRITE
Definition: audiohook.h:65
#define ast_test_flag(p, flag)
Definition: utils.h:63

Definition at line 162 of file audiohook.c.

Function Documentation

◆ ast_audiohook_attach()

int ast_audiohook_attach ( struct ast_channel chan,
struct ast_audiohook audiohook 
)

Attach audiohook to channel.

Parameters
chan
audiohook
Returns
0 on success
Return values
-1on failure

Definition at line 521 of file audiohook.c.

522{
523 ast_channel_lock(chan);
524
525 /* Don't allow an audiohook to be attached to a channel that is already hung up.
526 * The hang up process is what actually notifies the audiohook that it should
527 * stop.
528 */
530 ast_channel_unlock(chan);
531 return -1;
532 }
533
534 if (!ast_channel_audiohooks(chan)) {
535 struct ast_audiohook_list *ahlist;
536 /* Whoops... allocate a new structure */
537 if (!(ahlist = ast_calloc(1, sizeof(*ahlist)))) {
538 ast_channel_unlock(chan);
539 return -1;
540 }
541 ast_channel_audiohooks_set(chan, ahlist);
545 /* This sample rate will adjust as necessary when writing to the list. */
547 }
548
549 /* Drop into respective list */
550 if (audiohook->type == AST_AUDIOHOOK_TYPE_SPY) {
551 AST_LIST_INSERT_TAIL(&ast_channel_audiohooks(chan)->spy_list, audiohook, list);
552 } else if (audiohook->type == AST_AUDIOHOOK_TYPE_WHISPER) {
554 } else if (audiohook->type == AST_AUDIOHOOK_TYPE_MANIPULATE) {
556 }
557
558 /*
559 * Initialize the audiohook's rate to the default. If it needs to be,
560 * it will get updated later.
561 */
564
565 /* Change status over to running since it is now attached */
567
568 if (ast_channel_is_bridged(chan)) {
570 }
571
572 ast_channel_unlock(chan);
573
574 return 0;
575}
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
static void audiohook_list_set_samplerate_compatibility(struct ast_audiohook_list *audiohook_list)
Definition: audiohook.c:493
void ast_audiohook_update_status(struct ast_audiohook *audiohook, enum ast_audiohook_status status)
Update audiohook's status.
Definition: audiohook.c:577
static int audiohook_set_internal_rate(struct ast_audiohook *audiohook, int rate, int reset)
Definition: audiohook.c:70
#define DEFAULT_INTERNAL_SAMPLE_RATE
Definition: audiohook.c:48
@ AST_AUDIOHOOK_TYPE_MANIPULATE
Definition: audiohook.h:38
@ AST_AUDIOHOOK_TYPE_SPY
Definition: audiohook.h:36
@ AST_AUDIOHOOK_TYPE_WHISPER
Definition: audiohook.h:37
@ AST_AUDIOHOOK_STATUS_RUNNING
Definition: audiohook.h:43
void ast_channel_set_unbridged_nolock(struct ast_channel *chan, int value)
Variant of ast_channel_set_unbridged. Use this if the channel is already locked prior to calling.
#define ast_channel_lock(chan)
Definition: channel.h:2972
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
@ AST_FLAG_ZOMBIE
Definition: channel.h:1007
void ast_channel_audiohooks_set(struct ast_channel *chan, struct ast_audiohook_list *value)
struct ast_audiohook_list * ast_channel_audiohooks(const struct ast_channel *chan)
int ast_channel_is_bridged(const struct ast_channel *chan)
Determine if a channel is in a bridge.
Definition: channel.c:10546
#define ast_channel_unlock(chan)
Definition: channel.h:2973
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:681
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
int list_internal_samp_rate
Definition: audiohook.c:61
struct ast_audiohook_list::@307 spy_list
struct ast_audiohook_list::@308 whisper_list
struct ast_audiohook_list::@309 manipulate_list
enum ast_audiohook_type type
Definition: audiohook.h:107

References AST_AUDIOHOOK_STATUS_RUNNING, AST_AUDIOHOOK_TYPE_MANIPULATE, AST_AUDIOHOOK_TYPE_SPY, AST_AUDIOHOOK_TYPE_WHISPER, ast_audiohook_update_status(), ast_calloc, ast_channel_audiohooks(), ast_channel_audiohooks_set(), ast_channel_flags(), ast_channel_is_bridged(), ast_channel_lock, ast_channel_set_unbridged_nolock(), ast_channel_unlock, AST_FLAG_ZOMBIE, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_TAIL, ast_test_flag, audiohook_list_set_samplerate_compatibility(), audiohook_set_internal_rate(), DEFAULT_INTERNAL_SAMPLE_RATE, ast_audiohook_list::list_internal_samp_rate, ast_audiohook_list::manipulate_list, ast_audiohook_list::spy_list, ast_audiohook::type, and ast_audiohook_list::whisper_list.

Referenced by audiohook_move(), audiohook_volume_get(), detect_write(), enable_jack_hook(), init_hook(), pitchshift_helper(), scramble_write(), set_talk_detect(), snoop_setup_audiohook(), speex_write(), start_spying(), start_whispering(), startmon(), and volume_write().

◆ ast_audiohook_destroy()

int ast_audiohook_destroy ( struct ast_audiohook audiohook)

Destroys an audiohook structure.

Parameters
audiohook
Return values
0on success
-1on failure

Definition at line 124 of file audiohook.c.

125{
126 /* Drop the factories used by this audiohook type */
127 switch (audiohook->type) {
132 break;
133 default:
134 break;
135 }
136
137 /* Destroy translation path if present */
138 if (audiohook->trans_pvt)
140
141 ao2_cleanup(audiohook->format);
142
143 /* Lock and trigger be gone! */
144 ast_cond_destroy(&audiohook->trigger);
145 ast_mutex_destroy(&audiohook->lock);
146
147 return 0;
148}
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ast_cond_destroy(cond)
Definition: lock.h:209
#define ast_mutex_destroy(a)
Definition: lock.h:195
void ast_slinfactory_destroy(struct ast_slinfactory *sf)
Destroy the contents of a slinfactory.
Definition: slinfactory.c:58
ast_cond_t trigger
Definition: audiohook.h:106
struct ast_slinfactory read_factory
Definition: audiohook.h:112
struct ast_trans_pvt * trans_pvt
Definition: audiohook.h:117
struct ast_format * format
Definition: audiohook.h:116
ast_mutex_t lock
Definition: audiohook.h:105
struct ast_slinfactory write_factory
Definition: audiohook.h:113
void ast_translator_free_path(struct ast_trans_pvt *tr)
Frees a translator path Frees the given translator path structure.
Definition: translate.c:476

References ao2_cleanup, AST_AUDIOHOOK_TYPE_SPY, AST_AUDIOHOOK_TYPE_WHISPER, ast_cond_destroy, ast_mutex_destroy, ast_slinfactory_destroy(), ast_translator_free_path(), ast_audiohook::format, ast_audiohook::lock, ast_audiohook::read_factory, ast_audiohook::trans_pvt, ast_audiohook::trigger, ast_audiohook::type, and ast_audiohook::write_factory.

Referenced by audiohook_volume_destroy(), channel_spy(), datastore_destroy_cb(), destroy_callback(), destroy_jack_data(), destroy_monitor_audiohook(), hook_datastore_destroy_callback(), launch_monitor_thread(), multi_autochan_free(), and snoop_destroy().

◆ ast_audiohook_detach()

int ast_audiohook_detach ( struct ast_audiohook audiohook)

Detach audiohook from channel.

Parameters
audiohook
Returns
Returns 0 on success, -1 on failure

Definition at line 587 of file audiohook.c.

588{
589 if (audiohook->status == AST_AUDIOHOOK_STATUS_NEW || audiohook->status == AST_AUDIOHOOK_STATUS_DONE) {
590 return 0;
591 }
592
594
595 while (audiohook->status != AST_AUDIOHOOK_STATUS_DONE) {
597 }
598
599 return 0;
600}
void ast_audiohook_trigger_wait(struct ast_audiohook *audiohook)
Wait for audiohook trigger to be triggered.
Definition: audiohook.c:1131
@ AST_AUDIOHOOK_STATUS_DONE
Definition: audiohook.h:45
@ AST_AUDIOHOOK_STATUS_NEW
Definition: audiohook.h:42
@ AST_AUDIOHOOK_STATUS_SHUTDOWN
Definition: audiohook.h:44
enum ast_audiohook_status status
Definition: audiohook.h:108

References AST_AUDIOHOOK_STATUS_DONE, AST_AUDIOHOOK_STATUS_NEW, AST_AUDIOHOOK_STATUS_SHUTDOWN, ast_audiohook_trigger_wait(), ast_audiohook_update_status(), and ast_audiohook::status.

Referenced by channel_spy(), destroy_callback(), destroy_monitor_audiohook(), disable_jack_hook(), hook_datastore_destroy_callback(), multi_autochan_free(), snoop_hangup(), and speex_write().

◆ ast_audiohook_detach_list()

void ast_audiohook_detach_list ( struct ast_audiohook_list audiohook_list)

Detach audiohooks from list and destroy said list.

Parameters
audiohook_listList of audiohooks (NULL tolerant)

Definition at line 602 of file audiohook.c.

603{
604 int i;
605 struct ast_audiohook *audiohook;
606
607 if (!audiohook_list) {
608 return;
609 }
610
611 /* Drop any spies */
612 while ((audiohook = AST_LIST_REMOVE_HEAD(&audiohook_list->spy_list, list))) {
614 }
615
616 /* Drop any whispering sources */
617 while ((audiohook = AST_LIST_REMOVE_HEAD(&audiohook_list->whisper_list, list))) {
619 }
620
621 /* Drop any manipulators */
622 while ((audiohook = AST_LIST_REMOVE_HEAD(&audiohook_list->manipulate_list, list))) {
624 audiohook->manipulate_callback(audiohook, NULL, NULL, 0);
625 }
626
627 /* Drop translation paths if present */
628 for (i = 0; i < 2; i++) {
629 if (audiohook_list->in_translate[i].trans_pvt) {
631 ao2_cleanup(audiohook_list->in_translate[i].format);
632 }
633 if (audiohook_list->out_translate[i].trans_pvt) {
635 ao2_cleanup(audiohook_list->in_translate[i].format);
636 }
637 }
638
639 /* Free ourselves */
640 ast_free(audiohook_list);
641}
#define ast_free(a)
Definition: astmm.h:180
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
#define NULL
Definition: resample.c:96
struct ast_audiohook_translate out_translate[2]
Definition: audiohook.c:64
struct ast_audiohook_translate in_translate[2]
Definition: audiohook.c:63
struct ast_trans_pvt * trans_pvt
Definition: audiohook.c:51
struct ast_format * format
Definition: audiohook.c:52
ast_audiohook_manipulate_callback manipulate_callback
Definition: audiohook.h:118
struct ast_audiohook::@192 list

References ao2_cleanup, AST_AUDIOHOOK_STATUS_DONE, ast_audiohook_update_status(), ast_free, AST_LIST_REMOVE_HEAD, ast_translator_free_path(), ast_audiohook_translate::format, ast_audiohook_list::in_translate, ast_audiohook::list, ast_audiohook::manipulate_callback, ast_audiohook_list::manipulate_list, NULL, ast_audiohook_list::out_translate, ast_audiohook_list::spy_list, ast_audiohook_translate::trans_pvt, and ast_audiohook_list::whisper_list.

Referenced by __ast_read(), ast_write_stream(), and destroy_hooks().

◆ ast_audiohook_detach_source()

int ast_audiohook_detach_source ( struct ast_channel chan,
const char *  source 
)

Detach specified source audiohook from channel.

Parameters
chanChannel to detach from
sourceName of source to detach
Return values
0on success
-1on failure
Note
The channel does not need to be locked before calling this function.

Definition at line 735 of file audiohook.c.

736{
737 struct ast_audiohook *audiohook = NULL;
738
739 ast_channel_lock(chan);
740
741 /* Ensure the channel has audiohooks on it */
742 if (!ast_channel_audiohooks(chan)) {
743 ast_channel_unlock(chan);
744 return -1;
745 }
746
748
749 ast_channel_unlock(chan);
750
751 if (audiohook && audiohook->status != AST_AUDIOHOOK_STATUS_DONE) {
753 }
754
755 return (audiohook ? 0 : -1);
756}
static struct ast_audiohook * find_audiohook_by_source(struct ast_audiohook_list *audiohook_list, const char *source)
find an audiohook based on its source
Definition: audiohook.c:649
const char * source
Definition: audiohook.h:110

References AST_AUDIOHOOK_STATUS_DONE, AST_AUDIOHOOK_STATUS_SHUTDOWN, ast_audiohook_update_status(), ast_channel_audiohooks(), ast_channel_lock, ast_channel_unlock, find_audiohook_by_source(), NULL, ast_audiohook::source, and ast_audiohook::status.

◆ ast_audiohook_init()

int ast_audiohook_init ( struct ast_audiohook audiohook,
enum ast_audiohook_type  type,
const char *  source,
enum ast_audiohook_init_flags  flags 
)

Initialize an audiohook structure.

Parameters
audiohook
typeType of audiohook to initialize this as
sourceWho is initializing this audiohook
flags
Return values
0on success
-1on failure

Definition at line 100 of file audiohook.c.

101{
102 /* Need to keep the type and source */
103 audiohook->type = type;
104 audiohook->source = source;
105
106 /* Initialize lock that protects our audiohook */
107 ast_mutex_init(&audiohook->lock);
108 ast_cond_init(&audiohook->trigger, NULL);
109
110 audiohook->init_flags = init_flags;
111
112 /* Set direction to BOTH so that we feed frames in both directions */
114
115 /* initialize internal rate at 8khz, this will adjust if necessary */
117
118 /* Since we are just starting out... this audiohook is new */
120
121 return 0;
122}
@ AST_AUDIOHOOK_DIRECTION_BOTH
Definition: audiohook.h:51
static const char type[]
Definition: chan_ooh323.c:109
#define ast_cond_init(cond, attr)
Definition: lock.h:208
#define ast_mutex_init(pmutex)
Definition: lock.h:193
enum ast_audiohook_init_flags init_flags
Definition: audiohook.h:109
enum ast_audiohook_direction direction
Definition: audiohook.h:121

References AST_AUDIOHOOK_DIRECTION_BOTH, AST_AUDIOHOOK_STATUS_NEW, ast_audiohook_update_status(), ast_cond_init, ast_mutex_init, audiohook_set_internal_rate(), DEFAULT_INTERNAL_SAMPLE_RATE, ast_audiohook::direction, ast_audiohook::init_flags, ast_audiohook::lock, NULL, ast_audiohook::source, ast_audiohook::trigger, type, and ast_audiohook::type.

Referenced by attach_barge(), audiohook_volume_get(), channel_spy(), detect_write(), do_broadcast(), enable_jack_hook(), hook_state_alloc(), launch_monitor_thread(), pitchshift_helper(), scramble_write(), set_talk_detect(), snoop_setup_audiohook(), speex_write(), and volume_write().

◆ ast_audiohook_move_all()

void ast_audiohook_move_all ( struct ast_channel old_chan,
struct ast_channel new_chan 
)

Move all audiohooks from one channel to another.

Note
It is required that both old_chan and new_chan are locked prior to calling this function. Besides needing to protect the data within the channels, not locking these channels can lead to a potential deadlock.
Parameters
old_chanThe source of the audiohooks being moved
new_chanThe destination channel for the audiohooks to be moved to

Definition at line 709 of file audiohook.c.

710{
711 struct ast_audiohook *audiohook;
712 struct ast_audiohook_list *audiohook_list;
713
714 audiohook_list = ast_channel_audiohooks(old_chan);
715 if (!audiohook_list) {
716 return;
717 }
718
719 AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->spy_list, audiohook, list) {
720 audiohook_move(old_chan, new_chan, audiohook);
721 }
723
724 AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->whisper_list, audiohook, list) {
725 audiohook_move(old_chan, new_chan, audiohook);
726 }
728
729 AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->manipulate_list, audiohook, list) {
730 audiohook_move(old_chan, new_chan, audiohook);
731 }
733}
static void audiohook_move(struct ast_channel *old_chan, struct ast_channel *new_chan, struct ast_audiohook *audiohook)
Definition: audiohook.c:674
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:615
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:529

References ast_channel_audiohooks(), AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, audiohook_move(), ast_audiohook_list::manipulate_list, ast_audiohook_list::spy_list, and ast_audiohook_list::whisper_list.

Referenced by channel_do_masquerade().

◆ ast_audiohook_move_by_source()

void ast_audiohook_move_by_source ( struct ast_channel old_chan,
struct ast_channel new_chan,
const char *  source 
)

Move an audiohook from one channel to a new one.

Todo:
Currently only the first audiohook of a specific source found will be moved. We should add the capability to move multiple audiohooks from a single source as well.
Note
It is required that both old_chan and new_chan are locked prior to calling this function. Besides needing to protect the data within the channels, not locking these channels can lead to a potential deadlock
Parameters
old_chanThe source of the audiohook to move
new_chanThe destination to which we want the audiohook to move
sourceThe source of the audiohook we want to move

Definition at line 693 of file audiohook.c.

694{
695 struct ast_audiohook *audiohook;
696
697 if (!ast_channel_audiohooks(old_chan)) {
698 return;
699 }
700
702 if (!audiohook) {
703 return;
704 }
705
706 audiohook_move(old_chan, new_chan, audiohook);
707}

References ast_channel_audiohooks(), audiohook_move(), find_audiohook_by_source(), and ast_audiohook::source.

◆ ast_audiohook_read_frame()

struct ast_frame * ast_audiohook_read_frame ( struct ast_audiohook audiohook,
size_t  samples,
enum ast_audiohook_direction  direction,
struct ast_format format 
)

Reads a frame in from the audiohook structure.

Parameters
audiohook
samplesNumber of samples wanted
directionDirection the audio frame came from
formatFormat of frame remote side wants back
Returns
frame on success
Return values
NULLon failure

Definition at line 483 of file audiohook.c.

484{
485 return audiohook_read_frame_helper(audiohook, samples, direction, format, NULL, NULL);
486}
static struct ast_frame * audiohook_read_frame_helper(struct ast_audiohook *audiohook, size_t samples, enum ast_audiohook_direction direction, struct ast_format *format, struct ast_frame **read_reference, struct ast_frame **write_reference)
Definition: audiohook.c:421
direction

References audiohook_read_frame_helper(), NULL, and ast_frame::samples.

Referenced by snoop_read(), and spy_generate().

◆ ast_audiohook_read_frame_all()

struct ast_frame * ast_audiohook_read_frame_all ( struct ast_audiohook audiohook,
size_t  samples,
struct ast_format format,
struct ast_frame **  read_frame,
struct ast_frame **  write_frame 
)

Reads a frame in from the audiohook structure in mixed audio mode and copies read and write frame data to provided arguments.

Parameters
audiohook
samplesNumber of samples wanted
formatFormat of frame remote side wants back
read_frameif available, we'll copy the read buffer to this.
write_frameif available, we'll copy the write buffer to this.
Returns
frame on success
Return values
NULLon failure

Definition at line 488 of file audiohook.c.

489{
490 return audiohook_read_frame_helper(audiohook, samples, AST_AUDIOHOOK_DIRECTION_BOTH, format, read_frame, write_frame);
491}
static struct ast_frame * read_frame(struct ast_filestream *s, int *whennext)
Definition: file.c:919

References AST_AUDIOHOOK_DIRECTION_BOTH, audiohook_read_frame_helper(), read_frame(), and ast_frame::samples.

Referenced by mixmonitor_thread(), and spy_generate().

◆ ast_audiohook_remove()

int ast_audiohook_remove ( struct ast_channel chan,
struct ast_audiohook audiohook 
)

Remove an audiohook from a specified channel.

Parameters
chanChannel to remove from
audiohookAudiohook to remove
Return values
0on success
-1on failure
Note
The channel does not need to be locked before calling this function

Definition at line 758 of file audiohook.c.

759{
760 ast_channel_lock(chan);
761
762 if (!ast_channel_audiohooks(chan)) {
763 ast_channel_unlock(chan);
764 return -1;
765 }
766
767 if (audiohook->type == AST_AUDIOHOOK_TYPE_SPY) {
768 AST_LIST_REMOVE(&ast_channel_audiohooks(chan)->spy_list, audiohook, list);
769 } else if (audiohook->type == AST_AUDIOHOOK_TYPE_WHISPER) {
770 AST_LIST_REMOVE(&ast_channel_audiohooks(chan)->whisper_list, audiohook, list);
771 } else if (audiohook->type == AST_AUDIOHOOK_TYPE_MANIPULATE) {
772 AST_LIST_REMOVE(&ast_channel_audiohooks(chan)->manipulate_list, audiohook, list);
773 }
774
777
778 if (ast_channel_is_bridged(chan)) {
780 }
781
782 ast_channel_unlock(chan);
783
784 return 0;
785}
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
Definition: linkedlists.h:856

References AST_AUDIOHOOK_STATUS_DONE, AST_AUDIOHOOK_TYPE_MANIPULATE, AST_AUDIOHOOK_TYPE_SPY, AST_AUDIOHOOK_TYPE_WHISPER, ast_audiohook_update_status(), ast_channel_audiohooks(), ast_channel_is_bridged(), ast_channel_lock, ast_channel_set_unbridged_nolock(), ast_channel_unlock, AST_LIST_REMOVE, audiohook_list_set_samplerate_compatibility(), ast_audiohook::list, and ast_audiohook::type.

Referenced by audiohook_move(), remove_detect(), remove_scrambler(), remove_talk_detect(), and speex_write().

◆ ast_audiohook_set_frame_feed_direction()

int ast_audiohook_set_frame_feed_direction ( struct ast_audiohook audiohook,
enum ast_audiohook_direction  direction 
)

Sets direction on audiohook.

Parameters
audiohook
directionIn which direction should the audiohook feed frames, ie if we are snooping 'in', set direction to READ so that only the 'in' frames are fed to the slin factory
Return values
0on success
-1on failure due to audiohook already in use or in shutdown. Can only set direction on NEW audiohooks

Definition at line 150 of file audiohook.c.

151{
152 /* Only set the direction on new audiohooks */
153 if (audiohook->status != AST_AUDIOHOOK_STATUS_NEW) {
154 ast_debug(3, "Can not set direction on attached Audiohook %p\n", audiohook);
155 return -1;
156 }
157
158 audiohook->direction = direction;
159 return 0;
160}
#define ast_debug(level,...)
Log a DEBUG message.

References AST_AUDIOHOOK_STATUS_NEW, ast_debug, ast_audiohook::direction, and ast_audiohook::status.

Referenced by snoop_setup_audiohook(), and start_spying().

◆ ast_audiohook_set_mute()

int ast_audiohook_set_mute ( struct ast_channel chan,
const char *  source,
enum ast_audiohook_flags  flag,
int  clear 
)

Mute frames read from or written to a channel.

Parameters
chanChannel to muck with
sourceType of audiohook
flagwhich direction to set / clear
clearset or clear muted frames on direction based on flag parameter
Return values
0success
-1failure

Definition at line 1405 of file audiohook.c.

1406{
1407 struct ast_audiohook *audiohook = NULL;
1408
1409 ast_channel_lock(chan);
1410
1411 /* Ensure the channel has audiohooks on it */
1412 if (!ast_channel_audiohooks(chan)) {
1413 ast_channel_unlock(chan);
1414 return -1;
1415 }
1416
1418
1419 if (audiohook) {
1420 if (clear) {
1421 ast_clear_flag(audiohook, flag);
1422 } else {
1423 ast_set_flag(audiohook, flag);
1424 }
1425 }
1426
1427 ast_channel_unlock(chan);
1428
1429 return (audiohook ? 0 : -1);
1430}
long int flag
Definition: f2c.h:83
#define ast_clear_flag(p, flag)
Definition: utils.h:77
#define ast_set_flag(p, flag)
Definition: utils.h:70

References ast_channel_audiohooks(), ast_channel_lock, ast_channel_unlock, ast_clear_flag, ast_set_flag, find_audiohook_by_source(), NULL, and ast_audiohook::source.

◆ ast_audiohook_set_mute_all()

int ast_audiohook_set_mute_all ( struct ast_channel chan,
const char *  source,
enum ast_audiohook_flags  flag,
int  clear 
)

Mute frames read from or written for all audiohooks on a channel.

Parameters
chanChannel to muck with
sourceType of audiohooks
flagwhich direction to set / clear
clearset or clear muted frames on direction based on flag parameter
Return values
>=0number of muted audiohooks
-1failure

Definition at line 1432 of file audiohook.c.

1433{
1434 struct ast_audiohook *audiohook = NULL;
1435 int count = 0;
1436
1437 ast_channel_lock(chan);
1438
1439 if (!ast_channel_audiohooks(chan)) {
1440 ast_channel_unlock(chan);
1441 return -1;
1442 }
1443
1444 AST_LIST_TRAVERSE(&ast_channel_audiohooks(chan)->spy_list, audiohook, list) {
1445 if (!strcasecmp(audiohook->source, source)) {
1446 count++;
1447 if (clearmute) {
1448 ast_clear_flag(audiohook, flag);
1449 } else {
1450 ast_set_flag(audiohook, flag);
1451 }
1452 }
1453 }
1454
1455 ast_test_suite_event_notify("AUDIOHOOK_GROUP_MUTE_TOGGLE", "Channel: %s\r\nSource: %s\r\nCount: %d\r\n",
1456 ast_channel_name(chan), source, count);
1457
1458 ast_channel_unlock(chan);
1459
1460 return count;
1461}
const char * ast_channel_name(const struct ast_channel *chan)
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:189

References ast_channel_audiohooks(), ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_clear_flag, AST_LIST_TRAVERSE, ast_set_flag, ast_test_suite_event_notify, ast_audiohook::list, NULL, and ast_audiohook::source.

Referenced by manager_mute_mixmonitor().

◆ ast_audiohook_trigger_wait()

void ast_audiohook_trigger_wait ( struct ast_audiohook audiohook)

Wait for audiohook trigger to be triggered.

Parameters
audiohookAudiohook to wait on

Definition at line 1131 of file audiohook.c.

1132{
1133 struct timeval wait;
1134 struct timespec ts;
1135
1136 wait = ast_tvadd(ast_tvnow(), ast_samp2tv(50000, 1000));
1137 ts.tv_sec = wait.tv_sec;
1138 ts.tv_nsec = wait.tv_usec * 1000;
1139
1140 ast_cond_timedwait(&audiohook->trigger, &audiohook->lock, &ts);
1141
1142 return;
1143}
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:213
struct timeval ast_samp2tv(unsigned int _nsamp, unsigned int _rate)
Returns a timeval corresponding to the duration of n samples at rate r. Useful to convert samples to ...
Definition: time.h:282
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: extconf.c:2282
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159

References ast_cond_timedwait, ast_samp2tv(), ast_tvadd(), ast_tvnow(), ast_audiohook::lock, and ast_audiohook::trigger.

Referenced by ast_audiohook_detach(), and mixmonitor_thread().

◆ ast_audiohook_update_status()

void ast_audiohook_update_status ( struct ast_audiohook audiohook,
enum ast_audiohook_status  status 
)

Update audiohook's status.

Parameters
audiohook
status
Note
once status is updated to DONE, this function can not be used to set the status back to any other setting. Setting DONE effectively locks the status as such.

Definition at line 577 of file audiohook.c.

578{
579 ast_audiohook_lock(audiohook);
580 if (audiohook->status != AST_AUDIOHOOK_STATUS_DONE) {
581 audiohook->status = status;
582 ast_cond_signal(&audiohook->trigger);
583 }
584 ast_audiohook_unlock(audiohook);
585}
jack_status_t status
Definition: app_jack.c:149
#define ast_audiohook_lock(ah)
Lock an audiohook.
Definition: audiohook.h:313
#define ast_audiohook_unlock(ah)
Unlock an audiohook.
Definition: audiohook.h:318
#define ast_cond_signal(cond)
Definition: lock.h:210

References ast_audiohook_lock, AST_AUDIOHOOK_STATUS_DONE, ast_audiohook_unlock, ast_cond_signal, status, ast_audiohook::status, and ast_audiohook::trigger.

Referenced by ast_audiohook_attach(), ast_audiohook_detach(), ast_audiohook_detach_list(), ast_audiohook_detach_source(), ast_audiohook_init(), ast_audiohook_remove(), audio_audiohook_write_list(), dtmf_audiohook_write_list(), and stop_mixmonitor_full().

◆ ast_audiohook_volume_adjust()

int ast_audiohook_volume_adjust ( struct ast_channel chan,
enum ast_audiohook_direction  direction,
int  volume 
)

Adjust the volume on frames read from or written to a channel.

Parameters
chanChannel to muck with
directionDirection to increase
volumeValue to adjust the adjustment by
Return values
0on success
-1on failure
Since
1.6.1

Definition at line 1380 of file audiohook.c.

1381{
1382 return ast_audiohook_volume_adjust_float(chan, direction, (float) volume);
1383}
int ast_audiohook_volume_adjust_float(struct ast_channel *chan, enum ast_audiohook_direction direction, float volume)
Adjust the volume on frames read from or written to a channel.
Definition: audiohook.c:1385

References ast_audiohook_volume_adjust_float().

Referenced by execute_menu_entry().

◆ ast_audiohook_volume_adjust_float()

int ast_audiohook_volume_adjust_float ( struct ast_channel chan,
enum ast_audiohook_direction  direction,
float  volume 
)

Adjust the volume on frames read from or written to a channel.

Parameters
chanChannel to muck with
directionDirection to increase
volumeValue to adjust the adjustment by
Return values
0on success
-1on failure

Definition at line 1385 of file audiohook.c.

1386{
1388
1389 /* Attempt to find the audiohook volume information, and create an audiohook if none exists */
1390 if (!(audiohook_volume = audiohook_volume_get(chan, 1))) {
1391 return -1;
1392 }
1393
1394 /* Based on the direction change the specific adjustment value */
1397 }
1400 }
1401
1402 return 0;
1403}
static struct audiohook_volume * audiohook_volume_get(struct ast_channel *chan, int create)
Helper function which finds and optionally creates an audiohook_volume_datastore datastore on a chann...
Definition: audiohook.c:1295
Audiohook volume adjustment structure.
Definition: audiohook.c:1220
float read_adjustment
Definition: audiohook.c:1222
float write_adjustment
Definition: audiohook.c:1223

References AST_AUDIOHOOK_DIRECTION_BOTH, AST_AUDIOHOOK_DIRECTION_READ, AST_AUDIOHOOK_DIRECTION_WRITE, audiohook_volume_get(), NULL, audiohook_volume::read_adjustment, and audiohook_volume::write_adjustment.

Referenced by ast_audiohook_volume_adjust(), and ast_audiohook_volume_set().

◆ ast_audiohook_volume_get()

int ast_audiohook_volume_get ( struct ast_channel chan,
enum ast_audiohook_direction  direction 
)

Retrieve the volume adjustment value on frames read from or written to a channel.

Parameters
chanChannel to retrieve volume adjustment from
directionDirection to retrieve
Returns
adjustment value
Since
1.6.1

Definition at line 1355 of file audiohook.c.

1356{
1357 return (int) ast_audiohook_volume_get_float(chan, direction);
1358}
float ast_audiohook_volume_get_float(struct ast_channel *chan, enum ast_audiohook_direction direction)
Retrieve the volume adjustment value on frames read from or written to a channel.
Definition: audiohook.c:1360

References ast_audiohook_volume_get_float().

Referenced by confbridge_exec().

◆ ast_audiohook_volume_get_float()

float ast_audiohook_volume_get_float ( struct ast_channel chan,
enum ast_audiohook_direction  direction 
)

Retrieve the volume adjustment value on frames read from or written to a channel.

Parameters
chanChannel to retrieve volume adjustment from
directionDirection to retrieve
Returns
adjustment value

Definition at line 1360 of file audiohook.c.

1361{
1363 float adjustment = 0;
1364
1365 /* Attempt to find the audiohook volume information, but do not create it as we only want to look at the values */
1366 if (!(audiohook_volume = audiohook_volume_get(chan, 0))) {
1367 return 0;
1368 }
1369
1370 /* Grab the adjustment value based on direction given */
1372 adjustment = audiohook_volume->read_adjustment;
1374 adjustment = audiohook_volume->write_adjustment;
1375 }
1376
1377 return adjustment;
1378}

References AST_AUDIOHOOK_DIRECTION_READ, AST_AUDIOHOOK_DIRECTION_WRITE, audiohook_volume_get(), NULL, audiohook_volume::read_adjustment, and audiohook_volume::write_adjustment.

Referenced by ast_audiohook_volume_get().

◆ ast_audiohook_volume_set()

int ast_audiohook_volume_set ( struct ast_channel chan,
enum ast_audiohook_direction  direction,
int  volume 
)

Adjust the volume on frames read from or written to a channel.

Parameters
chanChannel to muck with
directionDirection to set on
volumeValue to adjust the volume by
Return values
0on success
-1on failure
Since
1.6.1

Definition at line 1330 of file audiohook.c.

1331{
1332 return ast_audiohook_volume_adjust_float(chan, direction, (float) volume);
1333}

References ast_audiohook_volume_adjust_float().

Referenced by confbridge_exec(), and execute_menu_entry().

◆ ast_audiohook_volume_set_float()

int ast_audiohook_volume_set_float ( struct ast_channel chan,
enum ast_audiohook_direction  direction,
float  volume 
)

Adjust the volume on frames read from or written to a channel.

Parameters
chanChannel to muck with
directionDirection to set on
volumeValue to adjust the volume by
Return values
0on success
-1on failure

Definition at line 1335 of file audiohook.c.

1336{
1338
1339 /* Attempt to find the audiohook volume information, but only create it if we are not setting the adjustment value to zero */
1340 if (!(audiohook_volume = audiohook_volume_get(chan, (volume ? 1 : 0)))) {
1341 return -1;
1342 }
1343
1344 /* Now based on the direction set the proper value */
1347 }
1350 }
1351
1352 return 0;
1353}

References AST_AUDIOHOOK_DIRECTION_BOTH, AST_AUDIOHOOK_DIRECTION_READ, AST_AUDIOHOOK_DIRECTION_WRITE, audiohook_volume_get(), NULL, audiohook_volume::read_adjustment, and audiohook_volume::write_adjustment.

◆ ast_audiohook_write_frame()

int ast_audiohook_write_frame ( struct ast_audiohook audiohook,
enum ast_audiohook_direction  direction,
struct ast_frame frame 
)

Writes a frame into the audiohook structure.

Parameters
audiohook
directionDirection the audio frame came from
frameFrame to write in
Return values
0on success
-1on failure

Definition at line 167 of file audiohook.c.

168{
169 struct ast_slinfactory *factory = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook->read_factory : &audiohook->write_factory);
170 struct ast_slinfactory *other_factory = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook->write_factory : &audiohook->read_factory);
171 struct timeval *rwtime = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook->read_time : &audiohook->write_time), previous_time = *rwtime;
172 int our_factory_samples;
173 int our_factory_ms;
174 int other_factory_samples;
175 int other_factory_ms;
176
177 /* Don't feed the frame if we are set to read and this is a write frame or if set to
178 write and this is a read frame as we don't want it. Plus, it can cause mis-resampling
179 if the READ and WRITE frames have different bitrates */
180 if (audiohook->direction != AST_AUDIOHOOK_DIRECTION_BOTH && audiohook->direction != direction) {
181 return 0;
182 }
183
184 /* Update last feeding time to be current */
185 *rwtime = ast_tvnow();
186
187 our_factory_samples = ast_slinfactory_available(factory);
188 our_factory_ms = ast_tvdiff_ms(*rwtime, previous_time) + (our_factory_samples / (audiohook->hook_internal_samp_rate / 1000));
189 other_factory_samples = ast_slinfactory_available(other_factory);
190 other_factory_ms = other_factory_samples / (audiohook->hook_internal_samp_rate / 1000);
191
192 if (ast_test_flag(audiohook, AST_AUDIOHOOK_TRIGGER_SYNC) && (our_factory_ms - other_factory_ms > AST_AUDIOHOOK_SYNC_TOLERANCE)) {
193 ast_debug(4, "Flushing audiohook %p so it remains in sync\n", audiohook);
194 ast_slinfactory_flush(factory);
195 ast_slinfactory_flush(other_factory);
196 }
197
198 if (ast_test_flag(audiohook, AST_AUDIOHOOK_SMALL_QUEUE) && ((our_factory_ms > AST_AUDIOHOOK_SMALL_QUEUE_TOLERANCE) || (other_factory_ms > AST_AUDIOHOOK_SMALL_QUEUE_TOLERANCE))) {
199 ast_debug(4, "Audiohook %p has stale audio in its factories. Flushing them both\n", audiohook);
200 ast_slinfactory_flush(factory);
201 ast_slinfactory_flush(other_factory);
202 } else if ((our_factory_ms > AST_AUDIOHOOK_LONG_QUEUE_TOLERANCE) || (other_factory_ms > AST_AUDIOHOOK_LONG_QUEUE_TOLERANCE)) {
203 ast_debug(4, "Audiohook %p has stale audio in its factories. Flushing them both\n", audiohook);
204 ast_slinfactory_flush(factory);
205 ast_slinfactory_flush(other_factory);
206 }
207
208 /* Write frame out to respective factory */
209 ast_slinfactory_feed(factory, frame);
210
211 /* If we need to notify the respective handler of this audiohook, do so */
213 ast_cond_signal(&audiohook->trigger);
215 ast_cond_signal(&audiohook->trigger);
216 } else if (ast_test_flag(audiohook, AST_AUDIOHOOK_TRIGGER_SYNC)) {
217 ast_cond_signal(&audiohook->trigger);
218 }
219
220 return 0;
221}
#define AST_AUDIOHOOK_LONG_QUEUE_TOLERANCE
Definition: audiohook.c:46
#define AST_AUDIOHOOK_SYNC_TOLERANCE
Definition: audiohook.c:44
#define AST_AUDIOHOOK_SMALL_QUEUE_TOLERANCE
Definition: audiohook.c:45
@ AST_AUDIOHOOK_TRIGGER_MODE
Definition: audiohook.h:55
@ AST_AUDIOHOOK_SMALL_QUEUE
Definition: audiohook.h:63
@ AST_AUDIOHOOK_TRIGGER_READ
Definition: audiohook.h:56
@ AST_AUDIOHOOK_TRIGGER_WRITE
Definition: audiohook.h:57
@ AST_AUDIOHOOK_TRIGGER_SYNC
Definition: audiohook.h:59
unsigned int ast_slinfactory_available(const struct ast_slinfactory *sf)
Retrieve number of samples currently in a slinfactory.
Definition: slinfactory.c:199
void ast_slinfactory_flush(struct ast_slinfactory *sf)
Flush the contents of a slinfactory.
Definition: slinfactory.c:204
int ast_slinfactory_feed(struct ast_slinfactory *sf, struct ast_frame *f)
Feed audio into a slinfactory.
Definition: slinfactory.c:77
struct timeval write_time
Definition: audiohook.h:115
struct timeval read_time
Definition: audiohook.h:114
unsigned int hook_internal_samp_rate
Definition: audiohook.h:120
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:107

References AST_AUDIOHOOK_DIRECTION_BOTH, AST_AUDIOHOOK_DIRECTION_READ, AST_AUDIOHOOK_DIRECTION_WRITE, AST_AUDIOHOOK_LONG_QUEUE_TOLERANCE, AST_AUDIOHOOK_SMALL_QUEUE, AST_AUDIOHOOK_SMALL_QUEUE_TOLERANCE, AST_AUDIOHOOK_SYNC_TOLERANCE, AST_AUDIOHOOK_TRIGGER_MODE, AST_AUDIOHOOK_TRIGGER_READ, AST_AUDIOHOOK_TRIGGER_SYNC, AST_AUDIOHOOK_TRIGGER_WRITE, ast_cond_signal, ast_debug, ast_slinfactory_available(), ast_slinfactory_feed(), ast_slinfactory_flush(), ast_test_flag, ast_tvdiff_ms(), ast_tvnow(), ast_audiohook::direction, ast_audiohook::hook_internal_samp_rate, ast_audiohook::read_factory, ast_audiohook::read_time, ast_audiohook::trigger, ast_audiohook::write_factory, and ast_audiohook::write_time.

Referenced by audio_audiohook_write_list(), channel_spy(), do_broadcast(), and snoop_write().

◆ ast_audiohook_write_list()

struct ast_frame * ast_audiohook_write_list ( struct ast_channel chan,
struct ast_audiohook_list audiohook_list,
enum ast_audiohook_direction  direction,
struct ast_frame frame 
)

Pass a frame off to be handled by the audiohook core.

Parameters
chanChannel that the list is coming off of
audiohook_listList of audiohooks
directionDirection frame is coming in from
frameThe frame itself
Returns
frame on success
Return values
NULLon failure

Definition at line 1116 of file audiohook.c.

1117{
1118 /* Pass off frame to it's respective list write function */
1119 if (frame->frametype == AST_FRAME_VOICE) {
1120 return audio_audiohook_write_list(chan, audiohook_list, direction, frame);
1121 } else if (frame->frametype == AST_FRAME_DTMF) {
1122 return dtmf_audiohook_write_list(chan, audiohook_list, direction, frame);
1123 } else {
1124 return frame;
1125 }
1126}
static struct ast_frame * audio_audiohook_write_list(struct ast_channel *chan, struct ast_audiohook_list *audiohook_list, enum ast_audiohook_direction direction, struct ast_frame *frame)
Pass an AUDIO frame off to be handled by the audiohook core.
Definition: audiohook.c:951
static struct ast_frame * dtmf_audiohook_write_list(struct ast_channel *chan, struct ast_audiohook_list *audiohook_list, enum ast_audiohook_direction direction, struct ast_frame *frame)
Pass a DTMF frame off to be handled by the audiohook core.
Definition: audiohook.c:795
#define AST_FRAME_DTMF
@ AST_FRAME_VOICE
enum ast_frame_type frametype

References AST_FRAME_DTMF, AST_FRAME_VOICE, audio_audiohook_write_list(), dtmf_audiohook_write_list(), and ast_frame::frametype.

Referenced by __ast_read(), and ast_write_stream().

◆ ast_audiohook_write_list_empty()

int ast_audiohook_write_list_empty ( struct ast_audiohook_list audiohook_list)

Determine if a audiohook_list is empty or not.

Parameters
audiohook_listAudiohook to check. (NULL also means empty)
Return values
0false
1true

Definition at line 1108 of file audiohook.c.

1109{
1110 return !audiohook_list
1111 || (AST_LIST_EMPTY(&audiohook_list->spy_list)
1112 && AST_LIST_EMPTY(&audiohook_list->whisper_list)
1113 && AST_LIST_EMPTY(&audiohook_list->manipulate_list));
1114}
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:450

References AST_LIST_EMPTY, ast_audiohook_list::manipulate_list, ast_audiohook_list::spy_list, and ast_audiohook_list::whisper_list.

Referenced by __ast_read(), ast_channel_has_audio_frame_or_monitor(), ast_channel_has_hook_requiring_audio(), and ast_write_stream().

◆ ast_channel_audiohook_count_by_source()

int ast_channel_audiohook_count_by_source ( struct ast_channel chan,
const char *  source,
enum ast_audiohook_type  type 
)

Find out how many audiohooks from a certain source exist on a given channel, regardless of status.

Parameters
chanThe channel on which to find the spies
sourceThe audiohook's source
typeThe type of audiohook
Returns
number of audiohooks which are from the source specified

Note: Function performs nlocking.

Definition at line 1146 of file audiohook.c.

1147{
1148 int count = 0;
1149 struct ast_audiohook *ah = NULL;
1150
1151 if (!ast_channel_audiohooks(chan)) {
1152 return -1;
1153 }
1154
1155 switch (type) {
1157 AST_LIST_TRAVERSE(&ast_channel_audiohooks(chan)->spy_list, ah, list) {
1158 if (!strcmp(ah->source, source)) {
1159 count++;
1160 }
1161 }
1162 break;
1164 AST_LIST_TRAVERSE(&ast_channel_audiohooks(chan)->whisper_list, ah, list) {
1165 if (!strcmp(ah->source, source)) {
1166 count++;
1167 }
1168 }
1169 break;
1171 AST_LIST_TRAVERSE(&ast_channel_audiohooks(chan)->manipulate_list, ah, list) {
1172 if (!strcmp(ah->source, source)) {
1173 count++;
1174 }
1175 }
1176 break;
1177 default:
1178 ast_debug(1, "Invalid audiohook type supplied, (%u)\n", type);
1179 return -1;
1180 }
1181
1182 return count;
1183}

References AST_AUDIOHOOK_TYPE_MANIPULATE, AST_AUDIOHOOK_TYPE_SPY, AST_AUDIOHOOK_TYPE_WHISPER, ast_channel_audiohooks(), ast_debug, AST_LIST_TRAVERSE, ast_audiohook::list, NULL, ast_audiohook::source, and type.

Referenced by feature_automixmonitor().

◆ ast_channel_audiohook_count_by_source_running()

int ast_channel_audiohook_count_by_source_running ( struct ast_channel chan,
const char *  source,
enum ast_audiohook_type  type 
)

Find out how many spies of a certain type exist on a given channel, and are in state running.

Parameters
chanThe channel on which to find the spies
sourceThe source of the audiohook
typeThe type of spy to look for
Returns
number of running audiohooks which are from the source specified

Note: Function performs no locking.

Definition at line 1186 of file audiohook.c.

1187{
1188 int count = 0;
1189 struct ast_audiohook *ah = NULL;
1190 if (!ast_channel_audiohooks(chan))
1191 return -1;
1192
1193 switch (type) {
1195 AST_LIST_TRAVERSE(&ast_channel_audiohooks(chan)->spy_list, ah, list) {
1196 if ((!strcmp(ah->source, source)) && (ah->status == AST_AUDIOHOOK_STATUS_RUNNING))
1197 count++;
1198 }
1199 break;
1201 AST_LIST_TRAVERSE(&ast_channel_audiohooks(chan)->whisper_list, ah, list) {
1202 if ((!strcmp(ah->source, source)) && (ah->status == AST_AUDIOHOOK_STATUS_RUNNING))
1203 count++;
1204 }
1205 break;
1207 AST_LIST_TRAVERSE(&ast_channel_audiohooks(chan)->manipulate_list, ah, list) {
1208 if ((!strcmp(ah->source, source)) && (ah->status == AST_AUDIOHOOK_STATUS_RUNNING))
1209 count++;
1210 }
1211 break;
1212 default:
1213 ast_debug(1, "Invalid audiohook type supplied, (%u)\n", type);
1214 return -1;
1215 }
1216 return count;
1217}

References AST_AUDIOHOOK_STATUS_RUNNING, AST_AUDIOHOOK_TYPE_MANIPULATE, AST_AUDIOHOOK_TYPE_SPY, AST_AUDIOHOOK_TYPE_WHISPER, ast_channel_audiohooks(), ast_debug, AST_LIST_TRAVERSE, ast_audiohook::list, NULL, ast_audiohook::source, ast_audiohook::status, and type.

◆ audio_audiohook_write_list()

static struct ast_frame * audio_audiohook_write_list ( struct ast_channel chan,
struct ast_audiohook_list audiohook_list,
enum ast_audiohook_direction  direction,
struct ast_frame frame 
)
static

Pass an AUDIO frame off to be handled by the audiohook core.

This function has 3 ast_frames and 3 parts to handle each. At the beginning of this function all 3 frames, start_frame, middle_frame, and end_frame point to the initial input frame.

Part_1: Translate the start_frame into SLINEAR audio if it is not already in that format. The result of this part is middle_frame is guaranteed to be in SLINEAR format for Part_2. Part_2: Send middle_frame off to spies and manipulators. At this point middle_frame is either a new frame as result of the translation, or points directly to the start_frame because no translation to SLINEAR audio was required. Part_3: Translate end_frame's audio back into the format of start frame if necessary. This is only necessary if manipulation of middle_frame occurred.

Parameters
chanChannel that the list is coming off of
audiohook_listList of audiohooks
directionDirection frame is coming in from
frameThe frame itself
Returns
frame on success
Return values
NULLon failure

Definition at line 951 of file audiohook.c.

952{
953 struct ast_frame *start_frame = frame, *middle_frame = frame, *end_frame = frame;
954 struct ast_audiohook *audiohook = NULL;
955 int samples;
956 int middle_frame_manipulated = 0;
957 int removed = 0;
958 int internal_sample_rate;
959
960 /* ---Part_1. translate start_frame to SLINEAR if necessary. */
961 if (!(middle_frame = audiohook_list_translate_to_slin(audiohook_list, direction, start_frame))) {
962 return frame;
963 }
964
965 /* If the translation resulted in an interpolated frame then immediately return as audiohooks
966 * rely on actual media being present to do things.
967 */
968 if (!middle_frame->data.ptr) {
969 if (middle_frame != start_frame) {
970 ast_frfree(middle_frame);
971 }
972 return start_frame;
973 }
974
975 samples = middle_frame->samples;
976
977 /*
978 * While processing each audiohook check to see if the internal sample rate needs
979 * to be adjusted (it should be the highest rate specified between formats and
980 * hooks). The given audiohook_list's internal sample rate is then set to the
981 * updated value before returning.
982 *
983 * If slin compatibility mode is turned on then an audiohook's internal sample
984 * rate is set to its audiohook_list's rate. If an audiohook_list's rate is
985 * adjusted during this pass then the change is picked up by the audiohooks
986 * on the next pass.
987 */
988 internal_sample_rate = audiohook_list->list_internal_samp_rate;
989
990 /* ---Part_2: Send middle_frame to spy and manipulator lists. middle_frame is guaranteed to be SLINEAR here.*/
991 /* Queue up signed linear frame to each spy */
992 AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->spy_list, audiohook, list) {
993 ast_audiohook_lock(audiohook);
994 if (audiohook->status != AST_AUDIOHOOK_STATUS_RUNNING) {
996 removed = 1;
998 ast_audiohook_unlock(audiohook);
999 if (ast_channel_is_bridged(chan)) {
1001 }
1002 continue;
1003 }
1004 audiohook_list_set_hook_rate(audiohook_list, audiohook, &internal_sample_rate);
1005 ast_audiohook_write_frame(audiohook, direction, middle_frame);
1006 ast_audiohook_unlock(audiohook);
1007 }
1009
1010 /* If this frame is being written out to the channel then we need to use whisper sources */
1011 if (!AST_LIST_EMPTY(&audiohook_list->whisper_list)) {
1012 int i = 0;
1013 short read_buf[samples], combine_buf[samples], *data1 = NULL, *data2 = NULL;
1014 memset(&combine_buf, 0, sizeof(combine_buf));
1015 AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->whisper_list, audiohook, list) {
1016 struct ast_slinfactory *factory = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook->read_factory : &audiohook->write_factory);
1017 ast_audiohook_lock(audiohook);
1018 if (audiohook->status != AST_AUDIOHOOK_STATUS_RUNNING) {
1020 removed = 1;
1022 ast_audiohook_unlock(audiohook);
1023 if (ast_channel_is_bridged(chan)) {
1025 }
1026 continue;
1027 }
1028 audiohook_list_set_hook_rate(audiohook_list, audiohook, &internal_sample_rate);
1029 if (ast_slinfactory_available(factory) >= samples && ast_slinfactory_read(factory, read_buf, samples)) {
1030 /* Take audio from this whisper source and combine it into our main buffer */
1031 for (i = 0, data1 = combine_buf, data2 = read_buf; i < samples; i++, data1++, data2++) {
1032 ast_slinear_saturated_add(data1, data2);
1033 }
1034 }
1035 ast_audiohook_unlock(audiohook);
1036 }
1038 /* We take all of the combined whisper sources and combine them into the audio being written out */
1039 for (i = 0, data1 = middle_frame->data.ptr, data2 = combine_buf; i < samples; i++, data1++, data2++) {
1040 ast_slinear_saturated_add(data1, data2);
1041 }
1042 middle_frame_manipulated = 1;
1043 }
1044
1045 /* Pass off frame to manipulate audiohooks */
1046 if (!AST_LIST_EMPTY(&audiohook_list->manipulate_list)) {
1047 AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->manipulate_list, audiohook, list) {
1048 ast_audiohook_lock(audiohook);
1049 if (audiohook->status != AST_AUDIOHOOK_STATUS_RUNNING) {
1051 removed = 1;
1053 ast_audiohook_unlock(audiohook);
1054 /* We basically drop all of our links to the manipulate audiohook and prod it to do it's own destructive things */
1055 audiohook->manipulate_callback(audiohook, chan, NULL, direction);
1056 if (ast_channel_is_bridged(chan)) {
1058 }
1059 continue;
1060 }
1061 audiohook_list_set_hook_rate(audiohook_list, audiohook, &internal_sample_rate);
1062 /*
1063 * Feed in frame to manipulation.
1064 */
1065 if (!audiohook->manipulate_callback(audiohook, chan, middle_frame, direction)) {
1066 /*
1067 * XXX FAILURES ARE IGNORED XXX
1068 * If the manipulation fails then the frame will be returned in its original state.
1069 * Since there are potentially more manipulator callbacks in the list, no action should
1070 * be taken here to exit early.
1071 */
1072 middle_frame_manipulated = 1;
1073 }
1074 ast_audiohook_unlock(audiohook);
1075 }
1077 }
1078
1079 /* ---Part_3: Decide what to do with the end_frame (whether to transcode or not) */
1080 if (middle_frame_manipulated) {
1081 if (!(end_frame = audiohook_list_translate_to_native(audiohook_list, direction, middle_frame, start_frame->subclass.format))) {
1082 /* translation failed, so just pass back the input frame */
1083 end_frame = start_frame;
1084 }
1085 } else {
1086 end_frame = start_frame;
1087 }
1088 /* clean up our middle_frame if required */
1089 if (middle_frame != end_frame) {
1090 ast_frfree(middle_frame);
1091 middle_frame = NULL;
1092 }
1093
1094 /* Before returning, if an audiohook got removed, reset samplerate compatibility */
1095 if (removed) {
1097 } else {
1098 /*
1099 * Set the audiohook_list's rate to the updated rate. Note that if a hook
1100 * was removed then the list's internal rate is reset to the default.
1101 */
1102 audiohook_list->list_internal_samp_rate = internal_sample_rate;
1103 }
1104
1105 return end_frame;
1106}
int ast_audiohook_write_frame(struct ast_audiohook *audiohook, enum ast_audiohook_direction direction, struct ast_frame *frame)
Writes a frame into the audiohook structure.
Definition: audiohook.c:167
static struct ast_frame * audiohook_list_translate_to_native(struct ast_audiohook_list *audiohook_list, enum ast_audiohook_direction direction, struct ast_frame *slin_frame, struct ast_format *outformat)
Definition: audiohook.c:873
static struct ast_frame * audiohook_list_translate_to_slin(struct ast_audiohook_list *audiohook_list, enum ast_audiohook_direction direction, struct ast_frame *frame)
Definition: audiohook.c:827
static void audiohook_list_set_hook_rate(struct ast_audiohook_list *audiohook_list, struct ast_audiohook *audiohook, int *rate)
Set the audiohook's internal sample rate to the audiohook_list's rate, but only when native slin comp...
Definition: audiohook.c:905
#define ast_frfree(fr)
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:557
int ast_slinfactory_read(struct ast_slinfactory *sf, short *buf, size_t samples)
Read samples from a slinfactory.
Definition: slinfactory.c:145
struct ast_format * format
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
static force_inline void ast_slinear_saturated_add(short *input, short *value)
Definition: utils.h:450

References AST_AUDIOHOOK_DIRECTION_READ, ast_audiohook_lock, AST_AUDIOHOOK_STATUS_DONE, AST_AUDIOHOOK_STATUS_RUNNING, ast_audiohook_unlock, ast_audiohook_update_status(), ast_audiohook_write_frame(), ast_channel_is_bridged(), ast_channel_set_unbridged_nolock(), ast_frfree, AST_LIST_EMPTY, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_slinear_saturated_add(), ast_slinfactory_available(), ast_slinfactory_read(), audiohook_list_set_hook_rate(), audiohook_list_set_samplerate_compatibility(), audiohook_list_translate_to_native(), audiohook_list_translate_to_slin(), ast_frame_subclass::format, ast_audiohook::list, ast_audiohook_list::list_internal_samp_rate, ast_audiohook::manipulate_callback, ast_audiohook_list::manipulate_list, NULL, ast_audiohook::read_factory, ast_frame::samples, ast_audiohook_list::spy_list, ast_audiohook::status, ast_frame::subclass, ast_audiohook_list::whisper_list, and ast_audiohook::write_factory.

Referenced by ast_audiohook_write_list().

◆ audiohook_list_set_hook_rate()

static void audiohook_list_set_hook_rate ( struct ast_audiohook_list audiohook_list,
struct ast_audiohook audiohook,
int *  rate 
)
static

Set the audiohook's internal sample rate to the audiohook_list's rate, but only when native slin compatibility is turned on.

Parameters
audiohook_listaudiohook_list data object
audiohookthe audiohook to update
ratethe current max internal sample rate

Definition at line 905 of file audiohook.c.

907{
908 /* The rate should always be the max between itself and the hook */
909 if (audiohook->hook_internal_samp_rate > *rate) {
910 *rate = audiohook->hook_internal_samp_rate;
911 }
912
913 /*
914 * If native slin compatibility is turned on then update the audiohook
915 * with the audiohook_list's current rate. Note, the audiohook's rate is
916 * set to the audiohook_list's rate and not the given rate. If there is
917 * a change in rate the hook's rate is changed on its next check.
918 */
919 if (audiohook_list->native_slin_compatible) {
921 audiohook_set_internal_rate(audiohook, audiohook_list->list_internal_samp_rate, 1);
922 } else {
924 }
925}
@ AST_AUDIOHOOK_COMPATIBLE
Definition: audiohook.h:66
int native_slin_compatible
Definition: audiohook.c:60

References AST_AUDIOHOOK_COMPATIBLE, ast_clear_flag, ast_set_flag, audiohook_set_internal_rate(), ast_audiohook::hook_internal_samp_rate, ast_audiohook_list::list_internal_samp_rate, and ast_audiohook_list::native_slin_compatible.

Referenced by audio_audiohook_write_list().

◆ audiohook_list_set_samplerate_compatibility()

static void audiohook_list_set_samplerate_compatibility ( struct ast_audiohook_list audiohook_list)
static

Definition at line 493 of file audiohook.c.

494{
495 struct ast_audiohook *ah = NULL;
496
497 /*
498 * Anytime the samplerate compatibility is set (attach/remove an audiohook) the
499 * list's internal sample rate needs to be reset so that the next time processing
500 * through write_list, if needed, it will get updated to the correct rate.
501 *
502 * A list's internal rate always chooses the higher between its own rate and a
503 * given rate. If the current rate is being driven by an audiohook that wanted a
504 * higher rate then when this audiohook is removed the list's rate would remain
505 * at that level when it should be lower, and with no way to lower it since any
506 * rate compared against it would be lower.
507 *
508 * By setting it back to the lowest rate it can recalculate the new highest rate.
509 */
511
512 audiohook_list->native_slin_compatible = 1;
513 AST_LIST_TRAVERSE(&audiohook_list->manipulate_list, ah, list) {
515 audiohook_list->native_slin_compatible = 0;
516 return;
517 }
518 }
519}
@ AST_AUDIOHOOK_MANIPULATE_ALL_RATES
Definition: audiohook.h:75

References AST_AUDIOHOOK_MANIPULATE_ALL_RATES, AST_LIST_TRAVERSE, DEFAULT_INTERNAL_SAMPLE_RATE, ast_audiohook::init_flags, ast_audiohook::list, ast_audiohook_list::list_internal_samp_rate, ast_audiohook_list::manipulate_list, ast_audiohook_list::native_slin_compatible, and NULL.

Referenced by ast_audiohook_attach(), ast_audiohook_remove(), audio_audiohook_write_list(), and dtmf_audiohook_write_list().

◆ audiohook_list_translate_to_native()

static struct ast_frame * audiohook_list_translate_to_native ( struct ast_audiohook_list audiohook_list,
enum ast_audiohook_direction  direction,
struct ast_frame slin_frame,
struct ast_format outformat 
)
static

Definition at line 873 of file audiohook.c.

875{
876 struct ast_audiohook_translate *out_translate = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook_list->out_translate[0] : &audiohook_list->out_translate[1]);
877 struct ast_frame *outframe = NULL;
878 if (ast_format_cmp(slin_frame->subclass.format, outformat) == AST_FORMAT_CMP_NOT_EQUAL) {
879 /* rebuild translators if necessary */
880 if (ast_format_cmp(out_translate->format, outformat) == AST_FORMAT_CMP_NOT_EQUAL) {
881 if (out_translate->trans_pvt) {
882 ast_translator_free_path(out_translate->trans_pvt);
883 }
884 if (!(out_translate->trans_pvt = ast_translator_build_path(outformat, slin_frame->subclass.format))) {
885 return NULL;
886 }
887 ao2_replace(out_translate->format, outformat);
888 }
889 /* translate back to the format the frame came in as. */
890 if (!(outframe = ast_translate(out_translate->trans_pvt, slin_frame, 0))) {
891 return NULL;
892 }
893 }
894 return outframe;
895}
#define ao2_replace(dst, src)
Replace one object reference with another cleaning up the original.
Definition: astobj2.h:501
enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
Compare two formats.
Definition: format.c:201
@ AST_FORMAT_CMP_NOT_EQUAL
Definition: format.h:38
struct ast_frame * ast_translate(struct ast_trans_pvt *tr, struct ast_frame *f, int consume)
translates one or more frames Apply an input frame into the translator and receive zero or one output...
Definition: translate.c:566
struct ast_trans_pvt * ast_translator_build_path(struct ast_format *dest, struct ast_format *source)
Builds a translator path Build a path (possibly NULL) from source to dest.
Definition: translate.c:486

References ao2_replace, AST_AUDIOHOOK_DIRECTION_READ, ast_format_cmp(), AST_FORMAT_CMP_NOT_EQUAL, ast_translate(), ast_translator_build_path(), ast_translator_free_path(), ast_frame_subclass::format, ast_audiohook_translate::format, NULL, ast_audiohook_list::out_translate, ast_frame::subclass, and ast_audiohook_translate::trans_pvt.

Referenced by audio_audiohook_write_list().

◆ audiohook_list_translate_to_slin()

static struct ast_frame * audiohook_list_translate_to_slin ( struct ast_audiohook_list audiohook_list,
enum ast_audiohook_direction  direction,
struct ast_frame frame 
)
static

Definition at line 827 of file audiohook.c.

829{
831 &audiohook_list->in_translate[0] : &audiohook_list->in_translate[1]);
832 struct ast_frame *new_frame = frame;
833 struct ast_format *slin;
834
835 /*
836 * If we are capable of sample rates other that 8khz, update the internal
837 * audiohook_list's rate and higher sample rate audio arrives. If native
838 * slin compatibility is turned on all audiohooks in the list will be
839 * updated as well during read/write processing.
840 */
841 audiohook_list->list_internal_samp_rate =
843
845 if (ast_format_cmp(frame->subclass.format, slin) == AST_FORMAT_CMP_EQUAL) {
846 return new_frame;
847 }
848
849 if (!in_translate->format ||
850 ast_format_cmp(frame->subclass.format, in_translate->format) != AST_FORMAT_CMP_EQUAL) {
851 struct ast_trans_pvt *new_trans;
852
853 new_trans = ast_translator_build_path(slin, frame->subclass.format);
854 if (!new_trans) {
855 return NULL;
856 }
857
858 if (in_translate->trans_pvt) {
859 ast_translator_free_path(in_translate->trans_pvt);
860 }
861 in_translate->trans_pvt = new_trans;
862
863 ao2_replace(in_translate->format, frame->subclass.format);
864 }
865
866 if (!(new_frame = ast_translate(in_translate->trans_pvt, frame, 0))) {
867 return NULL;
868 }
869
870 return new_frame;
871}
unsigned int ast_format_get_sample_rate(const struct ast_format *format)
Get the sample rate of a media format.
Definition: format.c:379
@ AST_FORMAT_CMP_EQUAL
Definition: format.h:36
struct ast_format * ast_format_cache_get_slin_by_rate(unsigned int rate)
Retrieve the best signed linear format given a sample rate.
Definition: format_cache.c:512
Definition of a media format.
Definition: format.c:43
Default structure for translators, with the basic fields and buffers, all allocated as part of the sa...
Definition: translate.h:213
#define MAX(a, b)
Definition: utils.h:233

References ao2_replace, AST_AUDIOHOOK_DIRECTION_READ, ast_format_cache_get_slin_by_rate(), ast_format_cmp(), AST_FORMAT_CMP_EQUAL, ast_format_get_sample_rate(), ast_translate(), ast_translator_build_path(), ast_translator_free_path(), ast_frame_subclass::format, ast_audiohook_translate::format, ast_audiohook_list::in_translate, ast_audiohook_list::list_internal_samp_rate, MAX, NULL, ast_frame::subclass, and ast_audiohook_translate::trans_pvt.

Referenced by audio_audiohook_write_list().

◆ audiohook_move()

static void audiohook_move ( struct ast_channel old_chan,
struct ast_channel new_chan,
struct ast_audiohook audiohook 
)
static

Definition at line 674 of file audiohook.c.

675{
676 enum ast_audiohook_status oldstatus;
677
678 /* By locking both channels and the audiohook, we can assure that
679 * another thread will not have a chance to read the audiohook's status
680 * as done, even though ast_audiohook_remove signals the trigger
681 * condition.
682 */
683 ast_audiohook_lock(audiohook);
684 oldstatus = audiohook->status;
685
686 ast_audiohook_remove(old_chan, audiohook);
687 ast_audiohook_attach(new_chan, audiohook);
688
689 audiohook->status = oldstatus;
690 ast_audiohook_unlock(audiohook);
691}
int ast_audiohook_remove(struct ast_channel *chan, struct ast_audiohook *audiohook)
Remove an audiohook from a specified channel.
Definition: audiohook.c:758
int ast_audiohook_attach(struct ast_channel *chan, struct ast_audiohook *audiohook)
Attach audiohook to channel.
Definition: audiohook.c:521
ast_audiohook_status
Definition: audiohook.h:41

References ast_audiohook_attach(), ast_audiohook_lock, ast_audiohook_remove(), ast_audiohook_unlock, and ast_audiohook::status.

Referenced by ast_audiohook_move_all(), and ast_audiohook_move_by_source().

◆ audiohook_read_frame_both()

static struct ast_frame * audiohook_read_frame_both ( struct ast_audiohook audiohook,
size_t  samples,
struct ast_frame **  read_reference,
struct ast_frame **  write_reference 
)
static

Definition at line 257 of file audiohook.c.

258{
259 int count;
260 int usable_read;
261 int usable_write;
262 short adjust_value;
263 short buf1[samples];
264 short buf2[samples];
265 short *read_buf = NULL;
266 short *write_buf = NULL;
267 struct ast_frame frame = {
269 .datalen = sizeof(buf1),
270 .samples = samples,
271 };
272
273 /* Make sure both factories have the required samples */
274 usable_read = (ast_slinfactory_available(&audiohook->read_factory) >= samples ? 1 : 0);
275 usable_write = (ast_slinfactory_available(&audiohook->write_factory) >= samples ? 1 : 0);
276
277 if (!usable_read && !usable_write) {
278 /* If both factories are unusable bail out */
279 ast_debug(3, "Read factory %p and write factory %p both fail to provide %zu samples\n", &audiohook->read_factory, &audiohook->write_factory, samples);
280 return NULL;
281 }
282
283 /* usable_read=1: indicates that read factory have the required samples
284 * usable_write=0: indicates that write factory have not the required samples
285 * usable_write, follows:
286 * 1. Due to RTT issues, the direction write frame has not been received,
287 * and it may take more than (samples/8)*2ms to receive it.
288 * 2. Due to packet loss, the direction write frame could not been received.
289 *
290 * (ast_tvdiff_ms(ast_tvnow(), audiohook->write_time) < (samples/8)*2)(Expression A): This ensures that
291 * packets on both sides can be read correctly even with RTT; however, if the RTT exceeds
292 * (samples/8)*2ms, it may result in the number of packets reading on both sides being greater than the
293 * actual number of packets. for example, this may cause the recording length of mixmonitor to be greater
294 * than the actual duration. Additionally, when RTT = 0 and packet loss is 50%, some packets in the
295 * write direction will never arrive. In this case, continuously waiting will only cause the read
296 * factory to exceed the safe length limit, resulting in both the read factory and write factory
297 * being cleared, thus same packets received in the read direction cannot be read.
298 *
299 * (ast_slinfactory_available(&audiohook->read_factory) < 2 * samples)(Expression B): This ensures that
300 * packets on both sides can be read correctly, even in the presence of packet loss; regardless of
301 * the amount of packet loss.
302 *
303 * (Expression A)&&(Expression B): This combination can comprehensively solve both RTT and packet loss
304 * issues; however when RTT exceeds (samples/8)*2ms, it may result in the number of packets read
305 * on both sides being greater than the actual number of packets, causing the recording length of
306 * mixmonitor to be longer than the actual duration. We can adjust (ast_tvdiff_ms(ast_tvnow(),
307 * audiohook->write_time)<(samples/8)*2) && (ast_slinfactory_available(&audiohook->read_factory) <
308 * 2 * samples) according to actual needs, for example, setting it to (ast_tvdiff_ms(ast_tvnow(),
309 * audiohook->write_time) < (samples/8)*4) && (ast_slinfactory_available(&audiohook->read_factory)
310 * < 4 * samples).
311 *
312 * Update:
313 * Increased time and sample thresholds allow for better handling of asymmetric streams
314 * (e.g., mixed codecs like alaw and G.722) and high RTT conditions.
315 * This avoids premature frame reads when one direction is delayed, which can cause
316 * audio tearing or broken recordings.
317 * Specifically addresses issues with MixMonitor when recording directly on a channel
318 * that is part of a bridge with different sample rates or codecs.
319 * A slight overrun in recording duration is acceptable in exchange for audio stability.
320 */
321 if (usable_read && !usable_write && (ast_tvdiff_ms(ast_tvnow(), audiohook->write_time) < (samples/8)*4) && (ast_slinfactory_available(&audiohook->read_factory) < 4 * samples)) {
322 ast_debug(3, "Write factory %p was pretty quick last time, waiting for them.\n", &audiohook->write_factory);
323 return NULL;
324 }
325
326 /* As shown in the above comment. */
327 if (usable_write && !usable_read && (ast_tvdiff_ms(ast_tvnow(), audiohook->read_time) < (samples/8)*4) && (ast_slinfactory_available(&audiohook->write_factory) < 4 * samples)) {
328 ast_debug(3, "Read factory %p was pretty quick last time, waiting for them.\n", &audiohook->read_factory);
329 return NULL;
330 }
331
332 /* Start with the read factory... if there are enough samples, read them in */
333 if (usable_read) {
334 if (ast_slinfactory_read(&audiohook->read_factory, buf1, samples)) {
335 read_buf = buf1;
336
337 if ((ast_test_flag(audiohook, AST_AUDIOHOOK_MUTE_READ))) {
338 /* Clear the frame data if we are muting */
339 memset(buf1, 0, sizeof(buf1));
340 } else if (audiohook->options.read_volume) {
341 /* Adjust read volume if need be */
342 adjust_value = abs(audiohook->options.read_volume);
343 for (count = 0; count < samples; count++) {
344 if (audiohook->options.read_volume > 0) {
345 ast_slinear_saturated_multiply(&buf1[count], &adjust_value);
346 } else if (audiohook->options.read_volume < 0) {
347 ast_slinear_saturated_divide(&buf1[count], &adjust_value);
348 }
349 }
350 }
351 }
352 } else {
353 ast_debug(1, "Failed to get %d samples from read factory %p\n", (int)samples, &audiohook->read_factory);
354 }
355
356 /* Move on to the write factory... if there are enough samples, read them in */
357 if (usable_write) {
358 if (ast_slinfactory_read(&audiohook->write_factory, buf2, samples)) {
359 write_buf = buf2;
360
361 if ((ast_test_flag(audiohook, AST_AUDIOHOOK_MUTE_WRITE))) {
362 /* Clear the frame data if we are muting */
363 memset(buf2, 0, sizeof(buf2));
364 } else if (audiohook->options.write_volume) {
365 /* Adjust write volume if need be */
366 adjust_value = abs(audiohook->options.write_volume);
367 for (count = 0; count < samples; count++) {
368 if (audiohook->options.write_volume > 0) {
369 ast_slinear_saturated_multiply(&buf2[count], &adjust_value);
370 } else if (audiohook->options.write_volume < 0) {
371 ast_slinear_saturated_divide(&buf2[count], &adjust_value);
372 }
373 }
374 }
375 }
376 } else {
377 ast_debug(3, "Failed to get %d samples from write factory %p\n", (int)samples, &audiohook->write_factory);
378 }
379
381
382 /* Should we substitute silence if one side lacks audio? */
384 if (read_reference && !read_buf && write_buf) {
385 read_buf = buf1;
386 memset(buf1, 0, sizeof(buf1));
387 } else if (write_reference && read_buf && !write_buf) {
388 write_buf = buf2;
389 memset(buf2, 0, sizeof(buf2));
390 }
391 }
392
393 /* Basically we figure out which buffer to use... and if mixing can be done here */
394 if (read_buf && read_reference) {
395 frame.data.ptr = read_buf;
396 *read_reference = ast_frdup(&frame);
397 }
398 if (write_buf && write_reference) {
399 frame.data.ptr = write_buf;
400 *write_reference = ast_frdup(&frame);
401 }
402
403 /* Make the correct buffer part of the built frame, so it gets duplicated. */
404 if (read_buf) {
405 frame.data.ptr = read_buf;
406 if (write_buf) {
407 for (count = 0; count < samples; count++) {
409 }
410 }
411 } else if (write_buf) {
412 frame.data.ptr = write_buf;
413 } else {
414 return NULL;
415 }
416
417 /* Yahoo, a combined copy of the audio! */
418 return ast_frdup(&frame);
419}
@ AST_AUDIOHOOK_SUBSTITUTE_SILENCE
Definition: audiohook.h:68
void write_buf(int file, char *buffer, int num)
Definition: eagi_proxy.c:312
#define abs(x)
Definition: f2c.h:195
static struct ast_threadstorage buf2
static struct ast_threadstorage buf1
#define ast_frdup(fr)
Copies a frame.
struct ast_audiohook_options options
Definition: audiohook.h:119
union ast_frame::@231 data
static force_inline void ast_slinear_saturated_multiply(short *input, short *value)
Definition: utils.h:476
static force_inline void ast_slinear_saturated_divide(short *input, short *value)
Definition: utils.h:505

References abs, AST_AUDIOHOOK_MUTE_READ, AST_AUDIOHOOK_MUTE_WRITE, AST_AUDIOHOOK_SUBSTITUTE_SILENCE, ast_debug, ast_format_cache_get_slin_by_rate(), AST_FRAME_VOICE, ast_frdup, ast_slinear_saturated_add(), ast_slinear_saturated_divide(), ast_slinear_saturated_multiply(), ast_slinfactory_available(), ast_slinfactory_read(), ast_test_flag, ast_tvdiff_ms(), ast_tvnow(), buf1, buf2, ast_frame::data, ast_frame_subclass::format, ast_frame::frametype, ast_audiohook::hook_internal_samp_rate, NULL, ast_audiohook::options, ast_frame::ptr, ast_audiohook::read_factory, ast_audiohook::read_time, ast_audiohook_options::read_volume, ast_frame::samples, ast_frame::subclass, write_buf(), ast_audiohook::write_factory, ast_audiohook::write_time, and ast_audiohook_options::write_volume.

Referenced by audiohook_read_frame_helper().

◆ audiohook_read_frame_helper()

static struct ast_frame * audiohook_read_frame_helper ( struct ast_audiohook audiohook,
size_t  samples,
enum ast_audiohook_direction  direction,
struct ast_format format,
struct ast_frame **  read_reference,
struct ast_frame **  write_reference 
)
static

Definition at line 421 of file audiohook.c.

422{
423 struct ast_frame *read_frame = NULL, *final_frame = NULL;
424 struct ast_format *slin;
425
426 /*
427 * Update the rate if compatibility mode is turned off or if it is
428 * turned on and the format rate is higher than the current rate.
429 *
430 * This makes it so any unnecessary rate switching/resetting does
431 * not take place and also any associated audiohook_list's internal
432 * sample rate maintains the highest sample rate between hooks.
433 */
434 if (!ast_test_flag(audiohook, AST_AUDIOHOOK_COMPATIBLE) ||
438 }
439
440 /* If the sample rate of the requested format differs from that of the underlying audiohook
441 * sample rate determine how many samples we actually need to get from the audiohook. This
442 * needs to occur as the signed linear factory stores them at the rate of the audiohook.
443 * We do this by determining the duration of audio they've requested and then determining
444 * how many samples that would be in the audiohook format.
445 */
446 if (ast_format_get_sample_rate(format) != audiohook->hook_internal_samp_rate) {
447 samples = (audiohook->hook_internal_samp_rate / 1000) * (samples / (ast_format_get_sample_rate(format) / 1000));
448 }
449
451 audiohook_read_frame_both(audiohook, samples, read_reference, write_reference) :
452 audiohook_read_frame_single(audiohook, samples, direction)))) {
453 return NULL;
454 }
455
457
458 /* If they don't want signed linear back out, we'll have to send it through the translation path */
459 if (ast_format_cmp(format, slin) != AST_FORMAT_CMP_EQUAL) {
460 /* Rebuild translation path if different format then previously */
461 if (ast_format_cmp(format, audiohook->format) == AST_FORMAT_CMP_NOT_EQUAL) {
462 if (audiohook->trans_pvt) {
464 audiohook->trans_pvt = NULL;
465 }
466
467 /* Setup new translation path for this format... if we fail we can't very well return signed linear so free the frame and return nothing */
468 if (!(audiohook->trans_pvt = ast_translator_build_path(format, slin))) {
470 return NULL;
471 }
472 ao2_replace(audiohook->format, format);
473 }
474 /* Convert to requested format, and allow the read in frame to be freed */
475 final_frame = ast_translate(audiohook->trans_pvt, read_frame, 1);
476 } else {
477 final_frame = read_frame;
478 }
479
480 return final_frame;
481}
static struct ast_frame * audiohook_read_frame_single(struct ast_audiohook *audiohook, size_t samples, enum ast_audiohook_direction direction)
Definition: audiohook.c:223
static struct ast_frame * audiohook_read_frame_both(struct ast_audiohook *audiohook, size_t samples, struct ast_frame **read_reference, struct ast_frame **write_reference)
Definition: audiohook.c:257

References ao2_replace, AST_AUDIOHOOK_COMPATIBLE, AST_AUDIOHOOK_DIRECTION_BOTH, ast_format_cache_get_slin_by_rate(), ast_format_cmp(), AST_FORMAT_CMP_EQUAL, AST_FORMAT_CMP_NOT_EQUAL, ast_format_get_sample_rate(), ast_frfree, ast_test_flag, ast_translate(), ast_translator_build_path(), ast_translator_free_path(), audiohook_read_frame_both(), audiohook_read_frame_single(), audiohook_set_internal_rate(), ast_audiohook::format, ast_audiohook::hook_internal_samp_rate, NULL, read_frame(), and ast_audiohook::trans_pvt.

Referenced by ast_audiohook_read_frame(), and ast_audiohook_read_frame_all().

◆ audiohook_read_frame_single()

static struct ast_frame * audiohook_read_frame_single ( struct ast_audiohook audiohook,
size_t  samples,
enum ast_audiohook_direction  direction 
)
static

Definition at line 223 of file audiohook.c.

224{
225 struct ast_slinfactory *factory = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook->read_factory : &audiohook->write_factory);
226 int vol = (direction == AST_AUDIOHOOK_DIRECTION_READ ? audiohook->options.read_volume : audiohook->options.write_volume);
227 short buf[samples];
228 struct ast_frame frame = {
230 .subclass.format = ast_format_cache_get_slin_by_rate(audiohook->hook_internal_samp_rate),
231 .data.ptr = buf,
232 .datalen = sizeof(buf),
233 .samples = samples,
234 };
235
236 /* Ensure the factory is able to give us the samples we want */
237 if (samples > ast_slinfactory_available(factory)) {
238 return NULL;
239 }
240
241 /* Read data in from factory */
242 if (!ast_slinfactory_read(factory, buf, samples)) {
243 return NULL;
244 }
245
246 if (SHOULD_MUTE(audiohook, direction)) {
247 /* Swap frame data for zeros if mute is required */
248 ast_frame_clear(&frame);
249 } else if (vol) {
250 /* If a volume adjustment needs to be applied apply it */
251 ast_frame_adjust_volume(&frame, vol);
252 }
253
254 return ast_frdup(&frame);
255}
#define SHOULD_MUTE(hook, dir)
Definition: audiohook.c:162
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
int ast_frame_clear(struct ast_frame *frame)
Clear all audio samples from an ast_frame. The frame must be AST_FRAME_VOICE and AST_FORMAT_SLINEAR.
Definition: main/frame.c:857
int ast_frame_adjust_volume(struct ast_frame *f, int adjustment)
Adjusts the volume of the audio samples contained in a frame.
Definition: main/frame.c:787

References AST_AUDIOHOOK_DIRECTION_READ, ast_format_cache_get_slin_by_rate(), ast_frame_adjust_volume(), ast_frame_clear(), AST_FRAME_VOICE, ast_frdup, ast_slinfactory_available(), ast_slinfactory_read(), buf, ast_frame::frametype, ast_audiohook::hook_internal_samp_rate, NULL, ast_audiohook::options, ast_audiohook::read_factory, ast_audiohook_options::read_volume, ast_frame::samples, SHOULD_MUTE, ast_audiohook::write_factory, and ast_audiohook_options::write_volume.

Referenced by audiohook_read_frame_helper().

◆ audiohook_set_internal_rate()

static int audiohook_set_internal_rate ( struct ast_audiohook audiohook,
int  rate,
int  reset 
)
static

Definition at line 70 of file audiohook.c.

71{
72 struct ast_format *slin;
73
74 if (audiohook->hook_internal_samp_rate == rate) {
75 return 0;
76 }
77
78 audiohook->hook_internal_samp_rate = rate;
79
81
82 /* Setup the factories that are needed for this audiohook type */
83 switch (audiohook->type) {
86 if (reset) {
89 }
92 break;
93 default:
94 break;
95 }
96
97 return 0;
98}
int ast_slinfactory_init_with_format(struct ast_slinfactory *sf, struct ast_format *slin_out)
Initialize a slinfactory.
Definition: slinfactory.c:46

References AST_AUDIOHOOK_TYPE_SPY, AST_AUDIOHOOK_TYPE_WHISPER, ast_format_cache_get_slin_by_rate(), ast_slinfactory_destroy(), ast_slinfactory_init_with_format(), ast_audiohook::hook_internal_samp_rate, ast_audiohook::read_factory, ast_audiohook::type, and ast_audiohook::write_factory.

Referenced by ast_audiohook_attach(), ast_audiohook_init(), audiohook_list_set_hook_rate(), and audiohook_read_frame_helper().

◆ audiohook_volume_callback()

static int audiohook_volume_callback ( struct ast_audiohook audiohook,
struct ast_channel chan,
struct ast_frame frame,
enum ast_audiohook_direction  direction 
)
static

Helper function which actually gets called by audiohooks to perform the adjustment.

Parameters
audiohookAudiohook attached to the channel
chanChannel we are attached to
frameFrame of audio we want to manipulate
directionDirection the audio came in from
Return values
0on success
-1on failure

Definition at line 1256 of file audiohook.c.

1257{
1258 struct ast_datastore *datastore = NULL;
1260 float *gain = NULL;
1261
1262 /* If the audiohook is shutting down don't even bother */
1264 return 0;
1265 }
1266
1267 /* Try to find the datastore containing adjustment information, if we can't just bail out */
1268 if (!(datastore = ast_channel_datastore_find(chan, &audiohook_volume_datastore, NULL))) {
1269 return 0;
1270 }
1271
1272 audiohook_volume = datastore->data;
1273
1274 /* Based on direction grab the appropriate adjustment value */
1279 }
1280
1281 /* If an adjustment value is present modify the frame */
1282 if (gain && *gain) {
1283 ast_frame_adjust_volume_float(frame, *gain);
1284 }
1285
1286 return 0;
1287}
static const struct ast_datastore_info audiohook_volume_datastore
Datastore used to store audiohook volume information.
Definition: audiohook.c:1243
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2368
int ast_frame_adjust_volume_float(struct ast_frame *f, float adjustment)
Adjusts the volume of the audio samples contained in a frame.
Definition: main/frame.c:812
Structure for a data store object.
Definition: datastore.h:64
void * data
Definition: datastore.h:66
struct ast_audiohook audiohook
Definition: audiohook.c:1221

References AST_AUDIOHOOK_DIRECTION_READ, AST_AUDIOHOOK_DIRECTION_WRITE, AST_AUDIOHOOK_STATUS_DONE, ast_channel_datastore_find(), ast_frame_adjust_volume_float(), audiohook_volume::audiohook, audiohook_volume_datastore, ast_datastore::data, NULL, audiohook_volume::read_adjustment, ast_audiohook::status, and audiohook_volume::write_adjustment.

Referenced by audiohook_volume_get().

◆ audiohook_volume_destroy()

static void audiohook_volume_destroy ( void *  data)
static

Callback used to destroy the audiohook volume datastore.

Parameters
dataVolume information structure

Definition at line 1229 of file audiohook.c.

1230{
1231 struct audiohook_volume *audiohook_volume = data;
1232
1233 /* Destroy the audiohook as it is no longer in use */
1235
1236 /* Finally free ourselves, we are of no more use */
1238
1239 return;
1240}
int ast_audiohook_destroy(struct ast_audiohook *audiohook)
Destroys an audiohook structure.
Definition: audiohook.c:124

References ast_audiohook_destroy(), ast_free, and audiohook_volume::audiohook.

◆ audiohook_volume_get()

static struct audiohook_volume * audiohook_volume_get ( struct ast_channel chan,
int  create 
)
static

Helper function which finds and optionally creates an audiohook_volume_datastore datastore on a channel.

Parameters
chanChannel to look on
createWhether to create the datastore if not found
Returns
audiohook_volume structure on success
Return values
NULLon failure

Definition at line 1295 of file audiohook.c.

1296{
1297 struct ast_datastore *datastore = NULL;
1299
1300 /* If we are able to find the datastore return the contents (which is actually an audiohook_volume structure) */
1301 if ((datastore = ast_channel_datastore_find(chan, &audiohook_volume_datastore, NULL))) {
1302 return datastore->data;
1303 }
1304
1305 /* If we are not allowed to create a datastore or if we fail to create a datastore, bail out now as we have nothing for them */
1306 if (!create || !(datastore = ast_datastore_alloc(&audiohook_volume_datastore, NULL))) {
1307 return NULL;
1308 }
1309
1310 /* Create a new audiohook_volume structure to contain our adjustments and audiohook */
1311 if (!(audiohook_volume = ast_calloc(1, sizeof(*audiohook_volume)))) {
1312 ast_datastore_free(datastore);
1313 return NULL;
1314 }
1315
1316 /* Setup our audiohook structure so we can manipulate the audio */
1319
1320 /* Attach the audiohook_volume blob to the datastore and attach to the channel */
1321 datastore->data = audiohook_volume;
1322 ast_channel_datastore_add(chan, datastore);
1323
1324 /* All is well... put the audiohook into motion */
1326
1327 return audiohook_volume;
1328}
static int audiohook_volume_callback(struct ast_audiohook *audiohook, struct ast_channel *chan, struct ast_frame *frame, enum ast_audiohook_direction direction)
Helper function which actually gets called by audiohooks to perform the adjustment.
Definition: audiohook.c:1256
int ast_audiohook_init(struct ast_audiohook *audiohook, enum ast_audiohook_type type, const char *source, enum ast_audiohook_init_flags init_flags)
Initialize an audiohook structure.
Definition: audiohook.c:100
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2354
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:85
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68

References ast_audiohook_attach(), ast_audiohook_init(), AST_AUDIOHOOK_MANIPULATE_ALL_RATES, AST_AUDIOHOOK_TYPE_MANIPULATE, ast_calloc, ast_channel_datastore_add(), ast_channel_datastore_find(), ast_datastore_alloc, ast_datastore_free(), audiohook_volume::audiohook, audiohook_volume_callback(), audiohook_volume_datastore, ast_datastore::data, ast_audiohook::manipulate_callback, and NULL.

Referenced by ast_audiohook_volume_adjust_float(), ast_audiohook_volume_get_float(), and ast_audiohook_volume_set_float().

◆ dtmf_audiohook_write_list()

static struct ast_frame * dtmf_audiohook_write_list ( struct ast_channel chan,
struct ast_audiohook_list audiohook_list,
enum ast_audiohook_direction  direction,
struct ast_frame frame 
)
static

Pass a DTMF frame off to be handled by the audiohook core.

Parameters
chanChannel that the list is coming off of
audiohook_listList of audiohooks
directionDirection frame is coming in from
frameThe frame itself
Returns
frame on success
Return values
NULLon failure

Definition at line 795 of file audiohook.c.

796{
797 struct ast_audiohook *audiohook = NULL;
798 int removed = 0;
799
800 AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->manipulate_list, audiohook, list) {
801 ast_audiohook_lock(audiohook);
802 if (audiohook->status != AST_AUDIOHOOK_STATUS_RUNNING) {
804 removed = 1;
806 ast_audiohook_unlock(audiohook);
807 audiohook->manipulate_callback(audiohook, NULL, NULL, 0);
808 if (ast_channel_is_bridged(chan)) {
810 }
811 continue;
812 }
813 if (ast_test_flag(audiohook, AST_AUDIOHOOK_WANTS_DTMF)) {
814 audiohook->manipulate_callback(audiohook, chan, frame, direction);
815 }
816 ast_audiohook_unlock(audiohook);
817 }
819
820 /* if an audiohook got removed, reset samplerate compatibility */
821 if (removed) {
823 }
824 return frame;
825}
@ AST_AUDIOHOOK_WANTS_DTMF
Definition: audiohook.h:58

References ast_audiohook_lock, AST_AUDIOHOOK_STATUS_DONE, AST_AUDIOHOOK_STATUS_RUNNING, ast_audiohook_unlock, ast_audiohook_update_status(), AST_AUDIOHOOK_WANTS_DTMF, ast_channel_is_bridged(), ast_channel_set_unbridged_nolock(), AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_test_flag, audiohook_list_set_samplerate_compatibility(), ast_audiohook::list, ast_audiohook::manipulate_callback, ast_audiohook_list::manipulate_list, NULL, and ast_audiohook::status.

Referenced by ast_audiohook_write_list().

◆ find_audiohook_by_source()

static struct ast_audiohook * find_audiohook_by_source ( struct ast_audiohook_list audiohook_list,
const char *  source 
)
static

find an audiohook based on its source

Parameters
audiohook_listThe list of audiohooks to search in
sourceThe source of the audiohook we wish to find
Returns
corresponding audiohook
Return values
NULLif it cannot be found

Definition at line 649 of file audiohook.c.

650{
651 struct ast_audiohook *audiohook = NULL;
652
653 AST_LIST_TRAVERSE(&audiohook_list->spy_list, audiohook, list) {
654 if (!strcasecmp(audiohook->source, source)) {
655 return audiohook;
656 }
657 }
658
659 AST_LIST_TRAVERSE(&audiohook_list->whisper_list, audiohook, list) {
660 if (!strcasecmp(audiohook->source, source)) {
661 return audiohook;
662 }
663 }
664
665 AST_LIST_TRAVERSE(&audiohook_list->manipulate_list, audiohook, list) {
666 if (!strcasecmp(audiohook->source, source)) {
667 return audiohook;
668 }
669 }
670
671 return NULL;
672}

References AST_LIST_TRAVERSE, ast_audiohook::list, ast_audiohook_list::manipulate_list, NULL, ast_audiohook::source, ast_audiohook_list::spy_list, and ast_audiohook_list::whisper_list.

Referenced by ast_audiohook_detach_source(), ast_audiohook_move_by_source(), and ast_audiohook_set_mute().

Variable Documentation

◆ audiohook_volume_datastore

const struct ast_datastore_info audiohook_volume_datastore
static
Initial value:
= {
.type = "Volume",
}
static void audiohook_volume_destroy(void *data)
Callback used to destroy the audiohook volume datastore.
Definition: audiohook.c:1229

Datastore used to store audiohook volume information.

Definition at line 1243 of file audiohook.c.

Referenced by audiohook_volume_callback(), and audiohook_volume_get().