Asterisk - The Open Source Telephony Project GIT-master-57e2743
Loading...
Searching...
No Matches
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/framehook.h"
#include "asterisk/timing.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...
 
struct  whisper_framehook_data
 

Macros

#define AST_AUDIOHOOK_LONG_QUEUE_TOLERANCE   500
 
#define AST_AUDIOHOOK_SMALL_QUEUE_TOLERANCE   100
 
#define AST_AUDIOHOOK_SYNC_TOLERANCE   100
 
#define AST_WHISPER_TIMER_CLAMP(interval)
 
#define AST_WHISPER_TIMER_INTERVAL   20
 
#define AST_WHISPER_TIMER_INTERVAL_MAX   60
 
#define AST_WHISPER_TIMER_INTERVAL_MIN   10
 
#define AST_WHISPER_TIMER_SRC   "audiohook whisper timer"
 
#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.
 
int ast_audiohook_destroy (struct ast_audiohook *audiohook)
 Destroys an audiohook structure.
 
int ast_audiohook_detach (struct ast_audiohook *audiohook)
 Detach audiohook from channel.
 
void ast_audiohook_detach_list (struct ast_audiohook_list *audiohook_list)
 Detach audiohooks from list and destroy said list.
 
int ast_audiohook_detach_source (struct ast_channel *chan, const char *source)
 Detach specified source audiohook from channel.
 
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.
 
void ast_audiohook_move_all (struct ast_channel *old_chan, struct ast_channel *new_chan)
 Move all audiohooks from one channel to another.
 
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.
 
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.
 
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.
 
int ast_audiohook_remove (struct ast_channel *chan, struct ast_audiohook *audiohook)
 Remove an audiohook from a specified channel.
 
int ast_audiohook_set_frame_feed_direction (struct ast_audiohook *audiohook, enum ast_audiohook_direction direction)
 Sets direction on audiohook.
 
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.
 
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.
 
void ast_audiohook_trigger_wait (struct ast_audiohook *audiohook)
 Wait for audiohook trigger to be triggered.
 
void ast_audiohook_update_status (struct ast_audiohook *audiohook, enum ast_audiohook_status status)
 Update audiohook's status.
 
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.
 
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.
 
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.
 
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.
 
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.
 
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.
 
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.
 
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.
 
int ast_audiohook_write_list_empty (struct ast_audiohook_list *audiohook_list)
 Determine if a audiohook_list is empty or not.
 
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.
 
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.
 
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.
 
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.
 
static void audiohook_list_set_samplerate_compatibility (struct ast_audiohook_list *audiohook_list)
 
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 struct ast_frame * audiohook_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_frame * audiohook_read_frame_both (struct ast_audiohook *audiohook, size_t samples, struct ast_frame **read_reference, struct ast_frame **write_reference)
 
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 struct ast_frame * audiohook_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.
 
static void audiohook_volume_destroy (void *data)
 Callback used to destroy the audiohook volume datastore.
 
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 channel.
 
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.
 
static struct ast_audiohook * find_audiohook_by_source (struct ast_audiohook_list *audiohook_list, const char *source)
 find an audiohook based on its source
 
static int whisper_framehook_attach (struct ast_channel *chan, struct ast_audiohook_list *audiohook_list)
 
static void whisper_framehook_breakdown (void *data, int framehook_id, struct ast_channel *old_chan, struct ast_channel *new_chan)
 
static void whisper_framehook_clear_fd (struct ast_channel *chan, struct whisper_framehook_data *hook_data)
 
static void whisper_framehook_destroy_cb (void *data)
 
static void whisper_framehook_detach (struct ast_channel *chan, struct ast_audiohook_list *audiohook_list)
 
static struct ast_frame * whisper_framehook_event_cb (struct ast_channel *chan, struct ast_frame *frame, enum ast_framehook_event event, void *data)
 
static void whisper_framehook_fixup (void *data, int framehook_id, struct ast_channel *old_chan, struct ast_channel *new_chan)
 
static void whisper_framehook_stop (struct ast_channel *chan, struct whisper_framehook_data *hook_data)
 
static void whisper_framehook_timer_start (struct ast_channel *chan, struct whisper_framehook_data *hook_data)
 
static void whisper_framehook_timer_stop (struct ast_channel *chan, struct whisper_framehook_data *hook_data)
 
static void whisper_framehook_timer_update (struct ast_audiohook_list *audiohook_list, struct ast_frame *start_frame, int internal_sample_rate, int samples)
 

Variables

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

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 48 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 47 of file audiohook.c.

◆ AST_AUDIOHOOK_SYNC_TOLERANCE

#define AST_AUDIOHOOK_SYNC_TOLERANCE   100

Tolerance in milliseconds for audiohooks synchronization

Definition at line 46 of file audiohook.c.

◆ AST_WHISPER_TIMER_CLAMP

#define AST_WHISPER_TIMER_CLAMP (   interval)
Value:
#define AST_WHISPER_TIMER_INTERVAL_MIN
Definition audiohook.c:50
#define AST_WHISPER_TIMER_INTERVAL_MAX
Definition audiohook.c:51

Definition at line 52 of file audiohook.c.

53 : \

◆ AST_WHISPER_TIMER_INTERVAL

#define AST_WHISPER_TIMER_INTERVAL   20

Definition at line 49 of file audiohook.c.

◆ AST_WHISPER_TIMER_INTERVAL_MAX

#define AST_WHISPER_TIMER_INTERVAL_MAX   60

Definition at line 51 of file audiohook.c.

◆ AST_WHISPER_TIMER_INTERVAL_MIN

#define AST_WHISPER_TIMER_INTERVAL_MIN   10

Definition at line 50 of file audiohook.c.

◆ AST_WHISPER_TIMER_SRC

#define AST_WHISPER_TIMER_SRC   "audiohook whisper timer"

Definition at line 55 of file audiohook.c.

◆ DEFAULT_INTERNAL_SAMPLE_RATE

#define DEFAULT_INTERNAL_SAMPLE_RATE   8000

Definition at line 57 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:64

Definition at line 460 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 819 of file audiohook.c.

820{
821 ast_channel_lock(chan);
822
823 /* Don't allow an audiohook to be attached to a channel that is already hung up.
824 * The hang up process is what actually notifies the audiohook that it should
825 * stop.
826 */
828 ast_channel_unlock(chan);
829 return -1;
830 }
831
832 if (!ast_channel_audiohooks(chan)) {
833 struct ast_audiohook_list *ahlist;
834 /* Whoops... allocate a new structure */
835 if (!(ahlist = ast_calloc(1, sizeof(*ahlist)))) {
836 ast_channel_unlock(chan);
837 return -1;
838 }
839 ast_channel_audiohooks_set(chan, ahlist);
843 /* This sample rate will adjust as necessary when writing to the list. */
846 }
847
848 /* Drop into respective list */
849 if (audiohook->type == AST_AUDIOHOOK_TYPE_SPY) {
850 AST_LIST_INSERT_TAIL(&ast_channel_audiohooks(chan)->spy_list, audiohook, list);
851 } else if (audiohook->type == AST_AUDIOHOOK_TYPE_WHISPER) {
852 int was_empty = AST_LIST_EMPTY(&ast_channel_audiohooks(chan)->whisper_list);
854 /* Only attach the framehook on the first whisper audiohook */
855 if (was_empty) {
857 AST_LIST_REMOVE(&ast_channel_audiohooks(chan)->whisper_list, audiohook, list);
858 ast_channel_unlock(chan);
859 return -1;
860 }
861 }
862 } else if (audiohook->type == AST_AUDIOHOOK_TYPE_MANIPULATE) {
864 }
865
866 /*
867 * Initialize the audiohook's rate to the default. If it needs to be,
868 * it will get updated later.
869 */
872
873 /* Change status over to running since it is now attached */
875
876 if (ast_channel_is_bridged(chan)) {
878 }
879
880 ast_channel_unlock(chan);
881
882 return 0;
883}
#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:791
void ast_audiohook_update_status(struct ast_audiohook *audiohook, enum ast_audiohook_status status)
Update audiohook's status.
Definition audiohook.c:885
static int whisper_framehook_attach(struct ast_channel *chan, struct ast_audiohook_list *audiohook_list)
Definition audiohook.c:316
static int audiohook_set_internal_rate(struct ast_audiohook *audiohook, int rate, int reset)
Definition audiohook.c:368
#define DEFAULT_INTERNAL_SAMPLE_RATE
Definition audiohook.c:57
@ 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:2983
@ AST_FLAG_ZOMBIE
Definition channel.h:1007
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
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:10725
#define ast_channel_unlock(chan)
Definition channel.h:2984
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
struct ast_audiohook_list::@322 spy_list
int list_internal_samp_rate
Definition audiohook.c:78
struct ast_audiohook_list::@323 whisper_list
struct ast_audiohook_list::@324 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_EMPTY, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_TAIL, AST_LIST_REMOVE, 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, whisper_framehook_attach(), ast_audiohook_list::whisper_framehook_id, 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_spying(), start_whispering(), 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 422 of file audiohook.c.

423{
424 /* Drop the factories used by this audiohook type */
425 switch (audiohook->type) {
430 break;
431 default:
432 break;
433 }
434
435 /* Destroy translation path if present */
436 if (audiohook->trans_pvt)
438
439 ao2_cleanup(audiohook->format);
440
441 /* Lock and trigger be gone! */
442 ast_cond_destroy(&audiohook->trigger);
443 ast_mutex_destroy(&audiohook->lock);
444
445 return 0;
446}
#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:533

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_callback(), destroy_callback(), destroy_callback(), destroy_callback(), destroy_jack_data(), destroy_monitor_audiohook(), hook_datastore_destroy_callback(), launch_monitor_thread(), mixmonitor_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 895 of file audiohook.c.

896{
897 if (audiohook->status == AST_AUDIOHOOK_STATUS_NEW || audiohook->status == AST_AUDIOHOOK_STATUS_DONE) {
898 return 0;
899 }
900
902
903 while (audiohook->status != AST_AUDIOHOOK_STATUS_DONE) {
905 }
906
907 return 0;
908}
void ast_audiohook_trigger_wait(struct ast_audiohook *audiohook)
Wait for audiohook trigger to be triggered.
Definition audiohook.c:1462
@ 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_callback(), 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 910 of file audiohook.c.

911{
912 int i;
913 struct ast_audiohook *audiohook;
914
915 if (!audiohook_list) {
916 return;
917 }
918
919 /* Drop any spies */
920 while ((audiohook = AST_LIST_REMOVE_HEAD(&audiohook_list->spy_list, list))) {
922 }
923
924 /* Drop any whispering sources */
925 while ((audiohook = AST_LIST_REMOVE_HEAD(&audiohook_list->whisper_list, list))) {
927 }
928
929 /* Drop any manipulators */
930 while ((audiohook = AST_LIST_REMOVE_HEAD(&audiohook_list->manipulate_list, list))) {
932 audiohook->manipulate_callback(audiohook, NULL, NULL, 0);
933 }
934
935 /* Drop translation paths if present */
936 for (i = 0; i < 2; i++) {
937 if (audiohook_list->in_translate[i].trans_pvt) {
939 ao2_cleanup(audiohook_list->in_translate[i].format);
940 }
941 if (audiohook_list->out_translate[i].trans_pvt) {
943 ao2_cleanup(audiohook_list->out_translate[i].format);
944 }
945 }
946
947 /* Free ourselves */
948 ast_free(audiohook_list);
949}
#define ast_free(a)
Definition astmm.h:180
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
#define NULL
Definition resample.c:96
struct ast_audiohook_translate out_translate[2]
Definition audiohook.c:81
struct ast_audiohook_translate in_translate[2]
Definition audiohook.c:80
struct ast_trans_pvt * trans_pvt
Definition audiohook.c:60
struct ast_format * format
Definition audiohook.c:61
ast_audiohook_manipulate_callback manipulate_callback
Definition audiohook.h:118
struct ast_audiohook::@196 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 1051 of file audiohook.c.

1052{
1053 struct ast_audiohook *audiohook = NULL;
1054
1055 ast_channel_lock(chan);
1056
1057 /* Ensure the channel has audiohooks on it */
1058 if (!ast_channel_audiohooks(chan)) {
1059 ast_channel_unlock(chan);
1060 return -1;
1061 }
1062
1064
1065 ast_channel_unlock(chan);
1066
1067 if (audiohook && audiohook->status != AST_AUDIOHOOK_STATUS_DONE) {
1069 }
1070
1071 return (audiohook ? 0 : -1);
1072}
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:957
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 398 of file audiohook.c.

399{
400 /* Need to keep the type and source */
401 audiohook->type = type;
402 audiohook->source = source;
403
404 /* Initialize lock that protects our audiohook */
405 ast_mutex_init(&audiohook->lock);
406 ast_cond_init(&audiohook->trigger, NULL);
407
408 audiohook->init_flags = init_flags;
409
410 /* Set direction to BOTH so that we feed frames in both directions */
412
413 /* initialize internal rate at 8khz, this will adjust if necessary */
415
416 /* Since we are just starting out... this audiohook is new */
418
419 return 0;
420}
@ AST_AUDIOHOOK_DIRECTION_BOTH
Definition audiohook.h:51
static const char type[]
#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(), 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 1025 of file audiohook.c.

1026{
1027 struct ast_audiohook *audiohook;
1028 struct ast_audiohook_list *audiohook_list;
1029
1030 audiohook_list = ast_channel_audiohooks(old_chan);
1031 if (!audiohook_list) {
1032 return;
1033 }
1034
1035 AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->spy_list, audiohook, list) {
1036 audiohook_move(old_chan, new_chan, audiohook);
1037 }
1039
1040 AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->whisper_list, audiohook, list) {
1041 audiohook_move(old_chan, new_chan, audiohook);
1042 }
1044
1045 AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->manipulate_list, audiohook, list) {
1046 audiohook_move(old_chan, new_chan, audiohook);
1047 }
1049}
static void audiohook_move(struct ast_channel *old_chan, struct ast_channel *new_chan, struct ast_audiohook *audiohook)
Definition audiohook.c:982
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.

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 1009 of file audiohook.c.

1010{
1011 struct ast_audiohook *audiohook;
1012
1013 if (!ast_channel_audiohooks(old_chan)) {
1014 return;
1015 }
1016
1018 if (!audiohook) {
1019 return;
1020 }
1021
1022 audiohook_move(old_chan, new_chan, audiohook);
1023}

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 781 of file audiohook.c.

782{
783 return audiohook_read_frame_helper(audiohook, samples, direction, format, NULL, NULL);
784}
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:719
direction

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

Referenced by snoop_read(), spy_generate(), 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
Note
The read_frame and write_frame may be in a different format from what was specified in format depending on the sample rate of the hooked channel's codec - ie; if we are requesting slin, but are hooked on channel using a 16K codec like g722, the read and write frames will be slin16.

Definition at line 786 of file audiohook.c.

787{
788 return audiohook_read_frame_helper(audiohook, samples, AST_AUDIOHOOK_DIRECTION_BOTH, format, read_frame, write_frame);
789}
static struct ast_frame * read_frame(struct ast_filestream *s, int *whennext)
Definition file.c:1000

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 1074 of file audiohook.c.

1075{
1076 ast_channel_lock(chan);
1077
1078 if (!ast_channel_audiohooks(chan)) {
1079 ast_channel_unlock(chan);
1080 return -1;
1081 }
1082
1083 if (audiohook->type == AST_AUDIOHOOK_TYPE_SPY) {
1084 AST_LIST_REMOVE(&ast_channel_audiohooks(chan)->spy_list, audiohook, list);
1085 } else if (audiohook->type == AST_AUDIOHOOK_TYPE_WHISPER) {
1086 AST_LIST_REMOVE(&ast_channel_audiohooks(chan)->whisper_list, audiohook, list);
1087 /* Detach the framehook if this was the last whisper audiohook */
1088 if (AST_LIST_EMPTY(&ast_channel_audiohooks(chan)->whisper_list)) {
1090 }
1091 } else if (audiohook->type == AST_AUDIOHOOK_TYPE_MANIPULATE) {
1092 AST_LIST_REMOVE(&ast_channel_audiohooks(chan)->manipulate_list, audiohook, list);
1093 }
1094
1097
1098 if (ast_channel_is_bridged(chan)) {
1100 }
1101
1102 ast_channel_unlock(chan);
1103
1104 return 0;
1105}
static void whisper_framehook_detach(struct ast_channel *chan, struct ast_audiohook_list *audiohook_list)
Definition audiohook.c:355

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_EMPTY, AST_LIST_REMOVE, audiohook_list_set_samplerate_compatibility(), ast_audiohook::list, ast_audiohook::type, and whisper_framehook_detach().

Referenced by audiohook_move(), mixmonitor_thread(), 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 448 of file audiohook.c.

449{
450 /* Only set the direction on new audiohooks */
451 if (audiohook->status != AST_AUDIOHOOK_STATUS_NEW) {
452 ast_debug(3, "Can not set direction on attached Audiohook %p\n", audiohook);
453 return -1;
454 }
455
456 audiohook->direction = direction;
457 return 0;
458}
#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(), start_spying(), 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 1736 of file audiohook.c.

1737{
1738 struct ast_audiohook *audiohook = NULL;
1739
1740 ast_channel_lock(chan);
1741
1742 /* Ensure the channel has audiohooks on it */
1743 if (!ast_channel_audiohooks(chan)) {
1744 ast_channel_unlock(chan);
1745 return -1;
1746 }
1747
1749
1750 if (audiohook) {
1751 if (clear) {
1752 ast_clear_flag(audiohook, flag);
1753 } else {
1754 ast_set_flag(audiohook, flag);
1755 }
1756 }
1757
1758 ast_channel_unlock(chan);
1759
1760 return (audiohook ? 0 : -1);
1761}
long int flag
Definition f2c.h:83
#define ast_clear_flag(p, flag)
Definition utils.h:78
#define ast_set_flag(p, flag)
Definition utils.h:71

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 1763 of file audiohook.c.

1764{
1765 struct ast_audiohook *audiohook = NULL;
1766 int count = 0;
1767
1768 ast_channel_lock(chan);
1769
1770 if (!ast_channel_audiohooks(chan)) {
1771 ast_channel_unlock(chan);
1772 return -1;
1773 }
1774
1775 AST_LIST_TRAVERSE(&ast_channel_audiohooks(chan)->spy_list, audiohook, list) {
1776 if (!strcasecmp(audiohook->source, source)) {
1777 count++;
1778 if (clearmute) {
1779 ast_clear_flag(audiohook, flag);
1780 } else {
1781 ast_set_flag(audiohook, flag);
1782 }
1783 }
1784 }
1785
1786 ast_test_suite_event_notify("AUDIOHOOK_GROUP_MUTE_TOGGLE", "Channel: %s\r\nSource: %s\r\nCount: %d\r\n",
1787 ast_channel_name(chan), source, count);
1788
1789 ast_channel_unlock(chan);
1790
1791 return count;
1792}
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.
#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 1462 of file audiohook.c.

1463{
1464 struct timeval wait;
1465 struct timespec ts;
1466
1467 wait = ast_tvadd(ast_tvnow(), ast_samp2tv(50000, 1000));
1468 ts.tv_sec = wait.tv_sec;
1469 ts.tv_nsec = wait.tv_usec * 1000;
1470
1471 ast_cond_timedwait(&audiohook->trigger, &audiohook->lock, &ts);
1472
1473 return;
1474}
#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:2278
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 885 of file audiohook.c.

886{
887 ast_audiohook_lock(audiohook);
888 if (audiohook->status != AST_AUDIOHOOK_STATUS_DONE) {
889 audiohook->status = status;
890 ast_cond_signal(&audiohook->trigger);
891 }
892 ast_audiohook_unlock(audiohook);
893}
jack_status_t status
Definition app_jack.c:149
#define ast_audiohook_lock(ah)
Lock an audiohook.
Definition audiohook.h:316
#define ast_audiohook_unlock(ah)
Unlock an audiohook.
Definition audiohook.h:321
#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 1711 of file audiohook.c.

1712{
1713 return ast_audiohook_volume_adjust_float(chan, direction, (float) volume);
1714}
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:1716

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 1716 of file audiohook.c.

1717{
1719
1720 /* Attempt to find the audiohook volume information, and create an audiohook if none exists */
1721 if (!(audiohook_volume = audiohook_volume_get(chan, 1))) {
1722 return -1;
1723 }
1724
1725 /* Based on the direction change the specific adjustment value */
1728 }
1731 }
1732
1733 return 0;
1734}
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:1626
Audiohook volume adjustment structure.
Definition audiohook.c:1551

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 1686 of file audiohook.c.

1687{
1688 return (int) ast_audiohook_volume_get_float(chan, direction);
1689}
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:1691

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 1691 of file audiohook.c.

1692{
1694 float adjustment = 0;
1695
1696 /* Attempt to find the audiohook volume information, but do not create it as we only want to look at the values */
1697 if (!(audiohook_volume = audiohook_volume_get(chan, 0))) {
1698 return 0;
1699 }
1700
1701 /* Grab the adjustment value based on direction given */
1703 adjustment = audiohook_volume->read_adjustment;
1705 adjustment = audiohook_volume->write_adjustment;
1706 }
1707
1708 return adjustment;
1709}

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 1661 of file audiohook.c.

1662{
1663 return ast_audiohook_volume_adjust_float(chan, direction, (float) volume);
1664}

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 1666 of file audiohook.c.

1667{
1669
1670 /* Attempt to find the audiohook volume information, but only create it if we are not setting the adjustment value to zero */
1671 if (!(audiohook_volume = audiohook_volume_get(chan, (volume ? 1 : 0)))) {
1672 return -1;
1673 }
1674
1675 /* Now based on the direction set the proper value */
1678 }
1681 }
1682
1683 return 0;
1684}

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 465 of file audiohook.c.

466{
467 struct ast_slinfactory *factory = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook->read_factory : &audiohook->write_factory);
468 struct ast_slinfactory *other_factory = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook->write_factory : &audiohook->read_factory);
469 struct timeval *rwtime = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook->read_time : &audiohook->write_time), previous_time = *rwtime;
470 int our_factory_samples;
471 int our_factory_ms;
472 int other_factory_samples;
473 int other_factory_ms;
474
475 /* Don't feed the frame if we are set to read and this is a write frame or if set to
476 write and this is a read frame as we don't want it. Plus, it can cause mis-resampling
477 if the READ and WRITE frames have different bitrates */
478 if (audiohook->direction != AST_AUDIOHOOK_DIRECTION_BOTH && audiohook->direction != direction) {
479 return 0;
480 }
481
482 /* Update last feeding time to be current */
483 *rwtime = ast_tvnow();
484
485 our_factory_samples = ast_slinfactory_available(factory);
486 our_factory_ms = ast_tvdiff_ms(*rwtime, previous_time) + (our_factory_samples / (audiohook->hook_internal_samp_rate / 1000));
487 other_factory_samples = ast_slinfactory_available(other_factory);
488 other_factory_ms = other_factory_samples / (audiohook->hook_internal_samp_rate / 1000);
489
490 if (ast_test_flag(audiohook, AST_AUDIOHOOK_TRIGGER_SYNC) && (our_factory_ms - other_factory_ms > AST_AUDIOHOOK_SYNC_TOLERANCE)) {
491 ast_debug(4, "Flushing audiohook %p so it remains in sync\n", audiohook);
492 ast_slinfactory_flush(factory);
493 ast_slinfactory_flush(other_factory);
494 }
495
496 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))) {
497 ast_debug(4, "Audiohook %p has stale audio in its factories. Flushing them both\n", audiohook);
498 ast_slinfactory_flush(factory);
499 ast_slinfactory_flush(other_factory);
500 } else if ((our_factory_ms > AST_AUDIOHOOK_LONG_QUEUE_TOLERANCE) || (other_factory_ms > AST_AUDIOHOOK_LONG_QUEUE_TOLERANCE)) {
501 ast_debug(4, "Audiohook %p has stale audio in its factories. Flushing them both\n", audiohook);
502 ast_slinfactory_flush(factory);
503 ast_slinfactory_flush(other_factory);
504 }
505
506 /* Write frame out to respective factory */
507 ast_slinfactory_feed(factory, frame);
508
509 /* If we need to notify the respective handler of this audiohook, do so */
511 ast_cond_signal(&audiohook->trigger);
513 ast_cond_signal(&audiohook->trigger);
514 } else if (ast_test_flag(audiohook, AST_AUDIOHOOK_TRIGGER_SYNC)) {
515 ast_cond_signal(&audiohook->trigger);
516 }
517
518 return 0;
519}
#define AST_AUDIOHOOK_LONG_QUEUE_TOLERANCE
Definition audiohook.c:48
#define AST_AUDIOHOOK_SYNC_TOLERANCE
Definition audiohook.c:46
#define AST_AUDIOHOOK_SMALL_QUEUE_TOLERANCE
Definition audiohook.c:47
@ 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.
void ast_slinfactory_flush(struct ast_slinfactory *sf)
Flush the contents of a slinfactory.
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 1447 of file audiohook.c.

1448{
1449 /* Pass off frame to it's respective list write function */
1450 if (frame->frametype == AST_FRAME_VOICE) {
1451 return audio_audiohook_write_list(chan, audiohook_list, direction, frame);
1452 } else if (frame->frametype == AST_FRAME_DTMF) {
1453 return dtmf_audiohook_write_list(chan, audiohook_list, direction, frame);
1454 } else {
1455 return frame;
1456 }
1457}
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:1271
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:1115
#define AST_FRAME_DTMF
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 1439 of file audiohook.c.

1440{
1441 return !audiohook_list
1442 || (AST_LIST_EMPTY(&audiohook_list->spy_list)
1443 && AST_LIST_EMPTY(&audiohook_list->whisper_list)
1444 && AST_LIST_EMPTY(&audiohook_list->manipulate_list));
1445}

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 1477 of file audiohook.c.

1478{
1479 int count = 0;
1480 struct ast_audiohook *ah = NULL;
1481
1482 if (!ast_channel_audiohooks(chan)) {
1483 return -1;
1484 }
1485
1486 switch (type) {
1488 AST_LIST_TRAVERSE(&ast_channel_audiohooks(chan)->spy_list, ah, list) {
1489 if (!strcmp(ah->source, source)) {
1490 count++;
1491 }
1492 }
1493 break;
1495 AST_LIST_TRAVERSE(&ast_channel_audiohooks(chan)->whisper_list, ah, list) {
1496 if (!strcmp(ah->source, source)) {
1497 count++;
1498 }
1499 }
1500 break;
1502 AST_LIST_TRAVERSE(&ast_channel_audiohooks(chan)->manipulate_list, ah, list) {
1503 if (!strcmp(ah->source, source)) {
1504 count++;
1505 }
1506 }
1507 break;
1508 default:
1509 ast_debug(1, "Invalid audiohook type supplied, (%u)\n", type);
1510 return -1;
1511 }
1512
1513 return count;
1514}

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 1517 of file audiohook.c.

1518{
1519 int count = 0;
1520 struct ast_audiohook *ah = NULL;
1521 if (!ast_channel_audiohooks(chan))
1522 return -1;
1523
1524 switch (type) {
1526 AST_LIST_TRAVERSE(&ast_channel_audiohooks(chan)->spy_list, ah, list) {
1527 if ((!strcmp(ah->source, source)) && (ah->status == AST_AUDIOHOOK_STATUS_RUNNING))
1528 count++;
1529 }
1530 break;
1532 AST_LIST_TRAVERSE(&ast_channel_audiohooks(chan)->whisper_list, ah, list) {
1533 if ((!strcmp(ah->source, source)) && (ah->status == AST_AUDIOHOOK_STATUS_RUNNING))
1534 count++;
1535 }
1536 break;
1538 AST_LIST_TRAVERSE(&ast_channel_audiohooks(chan)->manipulate_list, ah, list) {
1539 if ((!strcmp(ah->source, source)) && (ah->status == AST_AUDIOHOOK_STATUS_RUNNING))
1540 count++;
1541 }
1542 break;
1543 default:
1544 ast_debug(1, "Invalid audiohook type supplied, (%u)\n", type);
1545 return -1;
1546 }
1547 return count;
1548}

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 1271 of file audiohook.c.

1272{
1273 struct ast_frame *start_frame = frame, *middle_frame = frame, *end_frame = frame;
1274 struct ast_audiohook *audiohook = NULL;
1275 int samples;
1276 int middle_frame_manipulated = 0;
1277 int removed = 0;
1278 int internal_sample_rate;
1279
1280 /* ---Part_1. translate start_frame to SLINEAR if necessary. */
1281 if (!(middle_frame = audiohook_list_translate_to_slin(audiohook_list, direction, start_frame))) {
1282 return frame;
1283 }
1284
1285 /* If the translation resulted in an interpolated frame then immediately return as audiohooks
1286 * rely on actual media being present to do things.
1287 */
1288 if (!middle_frame->data.ptr) {
1289 if (middle_frame != start_frame) {
1290 ast_frfree(middle_frame);
1291 }
1292 return start_frame;
1293 }
1294
1295 samples = middle_frame->samples;
1296
1297 /*
1298 * While processing each audiohook check to see if the internal sample rate needs
1299 * to be adjusted (it should be the highest rate specified between formats and
1300 * hooks). The given audiohook_list's internal sample rate is then set to the
1301 * updated value before returning.
1302 *
1303 * If slin compatibility mode is turned on then an audiohook's internal sample
1304 * rate is set to its audiohook_list's rate. If an audiohook_list's rate is
1305 * adjusted during this pass then the change is picked up by the audiohooks
1306 * on the next pass.
1307 */
1308 internal_sample_rate = audiohook_list->list_internal_samp_rate;
1309
1310 /* ---Part_2: Send middle_frame to spy and manipulator lists. middle_frame is guaranteed to be SLINEAR here.*/
1311 /* Queue up signed linear frame to each spy */
1312 AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->spy_list, audiohook, list) {
1313 ast_audiohook_lock(audiohook);
1314 if (audiohook->status != AST_AUDIOHOOK_STATUS_RUNNING) {
1316 removed = 1;
1318 ast_audiohook_unlock(audiohook);
1319 if (ast_channel_is_bridged(chan)) {
1321 }
1322 continue;
1323 }
1324 audiohook_list_set_hook_rate(audiohook_list, audiohook, &internal_sample_rate);
1325 ast_audiohook_write_frame(audiohook, direction, middle_frame);
1326 ast_audiohook_unlock(audiohook);
1327 }
1329
1330 /* If this frame is being written out to the channel then we need to use whisper sources */
1331 if (!AST_LIST_EMPTY(&audiohook_list->whisper_list)) {
1332 int i = 0;
1333 short read_buf[samples], combine_buf[samples], *data1 = NULL, *data2 = NULL;
1334 memset(&combine_buf, 0, sizeof(combine_buf));
1335 AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->whisper_list, audiohook, list) {
1336 struct ast_slinfactory *factory = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook->read_factory : &audiohook->write_factory);
1337 ast_audiohook_lock(audiohook);
1338 if (audiohook->status != AST_AUDIOHOOK_STATUS_RUNNING) {
1340 removed = 1;
1342 ast_audiohook_unlock(audiohook);
1343 if (ast_channel_is_bridged(chan)) {
1345 }
1346 continue;
1347 }
1348 audiohook_list_set_hook_rate(audiohook_list, audiohook, &internal_sample_rate);
1349 if (ast_slinfactory_available(factory) >= samples && ast_slinfactory_read(factory, read_buf, samples)) {
1350 /* Take audio from this whisper source and combine it into our main buffer */
1351 for (i = 0, data1 = combine_buf, data2 = read_buf; i < samples; i++, data1++, data2++) {
1352 ast_slinear_saturated_add(data1, data2);
1353 }
1354 }
1355 ast_audiohook_unlock(audiohook);
1356 }
1358 /* We take all of the combined whisper sources and combine them into the audio being written out */
1359 for (i = 0, data1 = middle_frame->data.ptr, data2 = combine_buf; i < samples; i++, data1++, data2++) {
1360 ast_slinear_saturated_add(data1, data2);
1361 }
1362 middle_frame_manipulated = 1;
1363 }
1364
1365 /* Pass off frame to manipulate audiohooks */
1366 if (!AST_LIST_EMPTY(&audiohook_list->manipulate_list)) {
1367 AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->manipulate_list, audiohook, list) {
1368 ast_audiohook_lock(audiohook);
1369 if (audiohook->status != AST_AUDIOHOOK_STATUS_RUNNING) {
1371 removed = 1;
1373 ast_audiohook_unlock(audiohook);
1374 /* We basically drop all of our links to the manipulate audiohook and prod it to do it's own destructive things */
1375 audiohook->manipulate_callback(audiohook, chan, NULL, direction);
1376 if (ast_channel_is_bridged(chan)) {
1378 }
1379 continue;
1380 }
1381 audiohook_list_set_hook_rate(audiohook_list, audiohook, &internal_sample_rate);
1382 /*
1383 * Feed in frame to manipulation.
1384 */
1385 if (!audiohook->manipulate_callback(audiohook, chan, middle_frame, direction)) {
1386 /*
1387 * XXX FAILURES ARE IGNORED XXX
1388 * If the manipulation fails then the frame will be returned in its original state.
1389 * Since there are potentially more manipulator callbacks in the list, no action should
1390 * be taken here to exit early.
1391 */
1392 middle_frame_manipulated = 1;
1393 }
1394 ast_audiohook_unlock(audiohook);
1395 }
1397 }
1398
1399 /* ---Part_3: Decide what to do with the end_frame (whether to transcode or not) */
1400 if (middle_frame_manipulated) {
1401 if (!(end_frame = audiohook_list_translate_to_native(audiohook_list, direction, middle_frame, start_frame->subclass.format))) {
1402 /* translation failed, so just pass back the input frame */
1403 end_frame = start_frame;
1404 }
1405 } else {
1406 end_frame = start_frame;
1407 }
1408 /* clean up our middle_frame if required */
1409 if (middle_frame != end_frame) {
1410 ast_frfree(middle_frame);
1411 middle_frame = NULL;
1412 }
1413
1414 /* Before returning, if an audiohook got removed, reset samplerate compatibility */
1415 if (removed) {
1416 if (AST_LIST_EMPTY(&audiohook_list->whisper_list)) {
1417 whisper_framehook_detach(chan, audiohook_list);
1418 }
1420 } else {
1421 /*
1422 * Set the audiohook_list's rate to the updated rate. Note that if a hook
1423 * was removed then the list's internal rate is reset to the default.
1424 */
1425 audiohook_list->list_internal_samp_rate = internal_sample_rate;
1426 /*
1427 * Update the whisper timer with the internal sample rate on WRITE only to
1428 * avoid overlapping writes.
1429 */
1431 whisper_framehook_timer_update(audiohook_list, start_frame,
1432 internal_sample_rate, samples);
1433 }
1434 }
1435
1436 return end_frame;
1437}
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:465
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:1193
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:1147
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:1225
static void whisper_framehook_timer_update(struct ast_audiohook_list *audiohook_list, struct ast_frame *start_frame, int internal_sample_rate, int samples)
Definition audiohook.c:89
#define ast_frfree(fr)
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
int ast_slinfactory_read(struct ast_slinfactory *sf, short *buf, size_t samples)
Read samples from a slinfactory.
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:484

References AST_AUDIOHOOK_DIRECTION_READ, AST_AUDIOHOOK_DIRECTION_WRITE, 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, whisper_framehook_detach(), whisper_framehook_timer_update(), 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 1225 of file audiohook.c.

1227{
1228 /* The rate should always be the max between itself and the hook */
1229 if (audiohook->hook_internal_samp_rate > *rate) {
1230 *rate = audiohook->hook_internal_samp_rate;
1231 }
1232
1233 /*
1234 * If native slin compatibility is turned on then update the audiohook
1235 * with the audiohook_list's current rate. Note, the audiohook's rate is
1236 * set to the audiohook_list's rate and not the given rate. If there is
1237 * a change in rate the hook's rate is changed on its next check.
1238 */
1239 if (audiohook_list->native_slin_compatible) {
1241 audiohook_set_internal_rate(audiohook, audiohook_list->list_internal_samp_rate, 1);
1242 } else {
1244 }
1245}
@ AST_AUDIOHOOK_COMPATIBLE
Definition audiohook.h:66

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 791 of file audiohook.c.

792{
793 struct ast_audiohook *ah = NULL;
794
795 /*
796 * Anytime the samplerate compatibility is set (attach/remove an audiohook) the
797 * list's internal sample rate needs to be reset so that the next time processing
798 * through write_list, if needed, it will get updated to the correct rate.
799 *
800 * A list's internal rate always chooses the higher between its own rate and a
801 * given rate. If the current rate is being driven by an audiohook that wanted a
802 * higher rate then when this audiohook is removed the list's rate would remain
803 * at that level when it should be lower, and with no way to lower it since any
804 * rate compared against it would be lower.
805 *
806 * By setting it back to the lowest rate it can recalculate the new highest rate.
807 */
809
810 audiohook_list->native_slin_compatible = 1;
811 AST_LIST_TRAVERSE(&audiohook_list->manipulate_list, ah, list) {
813 audiohook_list->native_slin_compatible = 0;
814 return;
815 }
816 }
817}
@ 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 1193 of file audiohook.c.

1195{
1196 struct ast_audiohook_translate *out_translate = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook_list->out_translate[0] : &audiohook_list->out_translate[1]);
1197 struct ast_frame *outframe = NULL;
1198 if (ast_format_cmp(slin_frame->subclass.format, outformat) == AST_FORMAT_CMP_NOT_EQUAL) {
1199 /* rebuild translators if necessary */
1200 if (ast_format_cmp(out_translate->format, outformat) == AST_FORMAT_CMP_NOT_EQUAL) {
1201 if (out_translate->trans_pvt) {
1202 ast_translator_free_path(out_translate->trans_pvt);
1203 }
1204 if (!(out_translate->trans_pvt = ast_translator_build_path(outformat, slin_frame->subclass.format))) {
1205 return NULL;
1206 }
1207 ao2_replace(out_translate->format, outformat);
1208 }
1209 /* translate back to the format the frame came in as. */
1210 if (!(outframe = ast_translate(out_translate->trans_pvt, slin_frame, 0))) {
1211 return NULL;
1212 }
1213 }
1214 return outframe;
1215}
#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:623
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:543

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 1147 of file audiohook.c.

1149{
1151 &audiohook_list->in_translate[0] : &audiohook_list->in_translate[1]);
1152 struct ast_frame *new_frame = frame;
1153 struct ast_format *slin;
1154
1155 /*
1156 * If we are capable of sample rates other that 8khz, update the internal
1157 * audiohook_list's rate and higher sample rate audio arrives. If native
1158 * slin compatibility is turned on all audiohooks in the list will be
1159 * updated as well during read/write processing.
1160 */
1161 audiohook_list->list_internal_samp_rate =
1163
1165 if (ast_format_cmp(frame->subclass.format, slin) == AST_FORMAT_CMP_EQUAL) {
1166 return new_frame;
1167 }
1168
1169 if (!in_translate->format ||
1170 ast_format_cmp(frame->subclass.format, in_translate->format) != AST_FORMAT_CMP_EQUAL) {
1171 struct ast_trans_pvt *new_trans;
1172
1173 new_trans = ast_translator_build_path(slin, frame->subclass.format);
1174 if (!new_trans) {
1175 return NULL;
1176 }
1177
1178 if (in_translate->trans_pvt) {
1179 ast_translator_free_path(in_translate->trans_pvt);
1180 }
1181 in_translate->trans_pvt = new_trans;
1182
1183 ao2_replace(in_translate->format, frame->subclass.format);
1184 }
1185
1186 if (!(new_frame = ast_translate(in_translate->trans_pvt, frame, 0))) {
1187 return NULL;
1188 }
1189
1190 return new_frame;
1191}
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 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:254

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 982 of file audiohook.c.

983{
984 enum ast_audiohook_status oldstatus;
985
986 /* By locking both channels and the audiohook, we can assure that
987 * another thread will not have a chance to read the audiohook's status
988 * as done, even though ast_audiohook_remove signals the trigger
989 * condition.
990 */
991 ast_audiohook_lock(audiohook);
992 oldstatus = audiohook->status;
993
994 ast_audiohook_remove(old_chan, audiohook);
995 if (ast_audiohook_attach(new_chan, audiohook)) {
996 /*
997 * The audiohook is no longer on either channel. Leave it set to
998 * AST_AUDIOHOOK_STATUS_DONE as set by ast_audiohook_remove(), so
999 * that its owner does not wait forever.
1000 */
1001 ast_log(LOG_WARNING, "Unable to move audiohook '%s' to %s\n",
1002 audiohook->source, ast_channel_name(new_chan));
1003 } else {
1004 audiohook->status = oldstatus;
1005 }
1006 ast_audiohook_unlock(audiohook);
1007}
#define ast_log
Definition astobj2.c:42
int ast_audiohook_remove(struct ast_channel *chan, struct ast_audiohook *audiohook)
Remove an audiohook from a specified channel.
Definition audiohook.c:1074
int ast_audiohook_attach(struct ast_channel *chan, struct ast_audiohook *audiohook)
Attach audiohook to channel.
Definition audiohook.c:819
ast_audiohook_status
Definition audiohook.h:41
#define LOG_WARNING

References ast_audiohook_attach(), ast_audiohook_lock, ast_audiohook_remove(), ast_audiohook_unlock, ast_channel_name(), ast_log, LOG_WARNING, ast_audiohook::source, 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 555 of file audiohook.c.

556{
557 int count;
558 int usable_read;
559 int usable_write;
560 short adjust_value;
561 short buf1[samples];
562 short buf2[samples];
563 short *read_buf = NULL;
564 short *write_buf = NULL;
565 struct ast_frame frame = {
567 .datalen = sizeof(buf1),
568 .samples = samples,
569 };
570
571 /* Make sure both factories have the required samples */
572 usable_read = (ast_slinfactory_available(&audiohook->read_factory) >= samples ? 1 : 0);
573 usable_write = (ast_slinfactory_available(&audiohook->write_factory) >= samples ? 1 : 0);
574
575 if (!usable_read && !usable_write) {
576 /* If both factories are unusable bail out */
577 ast_debug(3, "Read factory %p and write factory %p both fail to provide %zu samples\n", &audiohook->read_factory, &audiohook->write_factory, samples);
578 return NULL;
579 }
580
581 /* usable_read=1: indicates that read factory have the required samples
582 * usable_write=0: indicates that write factory have not the required samples
583 * usable_write, follows:
584 * 1. Due to RTT issues, the direction write frame has not been received,
585 * and it may take more than (samples/8)*2ms to receive it.
586 * 2. Due to packet loss, the direction write frame could not been received.
587 *
588 * (ast_tvdiff_ms(ast_tvnow(), audiohook->write_time) < (samples/8)*2)(Expression A): This ensures that
589 * packets on both sides can be read correctly even with RTT; however, if the RTT exceeds
590 * (samples/8)*2ms, it may result in the number of packets reading on both sides being greater than the
591 * actual number of packets. for example, this may cause the recording length of mixmonitor to be greater
592 * than the actual duration. Additionally, when RTT = 0 and packet loss is 50%, some packets in the
593 * write direction will never arrive. In this case, continuously waiting will only cause the read
594 * factory to exceed the safe length limit, resulting in both the read factory and write factory
595 * being cleared, thus same packets received in the read direction cannot be read.
596 *
597 * (ast_slinfactory_available(&audiohook->read_factory) < 2 * samples)(Expression B): This ensures that
598 * packets on both sides can be read correctly, even in the presence of packet loss; regardless of
599 * the amount of packet loss.
600 *
601 * (Expression A)&&(Expression B): This combination can comprehensively solve both RTT and packet loss
602 * issues; however when RTT exceeds (samples/8)*2ms, it may result in the number of packets read
603 * on both sides being greater than the actual number of packets, causing the recording length of
604 * mixmonitor to be longer than the actual duration. We can adjust (ast_tvdiff_ms(ast_tvnow(),
605 * audiohook->write_time)<(samples/8)*2) && (ast_slinfactory_available(&audiohook->read_factory) <
606 * 2 * samples) according to actual needs, for example, setting it to (ast_tvdiff_ms(ast_tvnow(),
607 * audiohook->write_time) < (samples/8)*4) && (ast_slinfactory_available(&audiohook->read_factory)
608 * < 4 * samples).
609 *
610 * Update:
611 * Increased time and sample thresholds allow for better handling of asymmetric streams
612 * (e.g., mixed codecs like alaw and G.722) and high RTT conditions.
613 * This avoids premature frame reads when one direction is delayed, which can cause
614 * audio tearing or broken recordings.
615 * Specifically addresses issues with MixMonitor when recording directly on a channel
616 * that is part of a bridge with different sample rates or codecs.
617 * A slight overrun in recording duration is acceptable in exchange for audio stability.
618 */
619 if (usable_read && !usable_write && (ast_tvdiff_ms(ast_tvnow(), audiohook->write_time) < (samples/8)*4) && (ast_slinfactory_available(&audiohook->read_factory) < 4 * samples)) {
620 ast_debug(3, "Write factory %p was pretty quick last time, waiting for them.\n", &audiohook->write_factory);
621 return NULL;
622 }
623
624 /* As shown in the above comment. */
625 if (usable_write && !usable_read && (ast_tvdiff_ms(ast_tvnow(), audiohook->read_time) < (samples/8)*4) && (ast_slinfactory_available(&audiohook->write_factory) < 4 * samples)) {
626 ast_debug(3, "Read factory %p was pretty quick last time, waiting for them.\n", &audiohook->read_factory);
627 return NULL;
628 }
629
630 /* Start with the read factory... if there are enough samples, read them in */
631 if (usable_read) {
632 if (ast_slinfactory_read(&audiohook->read_factory, buf1, samples)) {
633 read_buf = buf1;
634
635 if ((ast_test_flag(audiohook, AST_AUDIOHOOK_MUTE_READ))) {
636 /* Clear the frame data if we are muting */
637 memset(buf1, 0, sizeof(buf1));
638 } else if (audiohook->options.read_volume) {
639 /* Adjust read volume if need be */
640 adjust_value = abs(audiohook->options.read_volume);
641 for (count = 0; count < samples; count++) {
642 if (audiohook->options.read_volume > 0) {
643 ast_slinear_saturated_multiply(&buf1[count], &adjust_value);
644 } else if (audiohook->options.read_volume < 0) {
645 ast_slinear_saturated_divide(&buf1[count], &adjust_value);
646 }
647 }
648 }
649 }
650 } else {
651 ast_debug(1, "Failed to get %d samples from read factory %p\n", (int)samples, &audiohook->read_factory);
652 }
653
654 /* Move on to the write factory... if there are enough samples, read them in */
655 if (usable_write) {
656 if (ast_slinfactory_read(&audiohook->write_factory, buf2, samples)) {
657 write_buf = buf2;
658
659 if ((ast_test_flag(audiohook, AST_AUDIOHOOK_MUTE_WRITE))) {
660 /* Clear the frame data if we are muting */
661 memset(buf2, 0, sizeof(buf2));
662 } else if (audiohook->options.write_volume) {
663 /* Adjust write volume if need be */
664 adjust_value = abs(audiohook->options.write_volume);
665 for (count = 0; count < samples; count++) {
666 if (audiohook->options.write_volume > 0) {
667 ast_slinear_saturated_multiply(&buf2[count], &adjust_value);
668 } else if (audiohook->options.write_volume < 0) {
669 ast_slinear_saturated_divide(&buf2[count], &adjust_value);
670 }
671 }
672 }
673 }
674 } else {
675 ast_debug(3, "Failed to get %d samples from write factory %p\n", (int)samples, &audiohook->write_factory);
676 }
677
679
680 /* Should we substitute silence if one side lacks audio? */
682 if (read_reference && !read_buf && write_buf) {
683 read_buf = buf1;
684 memset(buf1, 0, sizeof(buf1));
685 } else if (write_reference && read_buf && !write_buf) {
686 write_buf = buf2;
687 memset(buf2, 0, sizeof(buf2));
688 }
689 }
690
691 /* Basically we figure out which buffer to use... and if mixing can be done here */
692 if (read_buf && read_reference) {
693 frame.data.ptr = read_buf;
694 *read_reference = ast_frdup(&frame);
695 }
696 if (write_buf && write_reference) {
697 frame.data.ptr = write_buf;
698 *write_reference = ast_frdup(&frame);
699 }
700
701 /* Make the correct buffer part of the built frame, so it gets duplicated. */
702 if (read_buf) {
703 frame.data.ptr = read_buf;
704 if (write_buf) {
705 for (count = 0; count < samples; count++) {
707 }
708 }
709 } else if (write_buf) {
710 frame.data.ptr = write_buf;
711 } else {
712 return NULL;
713 }
714
715 /* Yahoo, a combined copy of the audio! */
716 return ast_frdup(&frame);
717}
@ 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
#define ast_frdup(fr)
Copies a frame.
struct ast_audiohook_options options
Definition audiohook.h:119
union ast_frame::@237 data
static force_inline void ast_slinear_saturated_multiply(short *input, short *value)
Definition utils.h:510
static force_inline void ast_slinear_saturated_divide(short *input, short *value)
Definition utils.h:539

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(), 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 719 of file audiohook.c.

720{
721 struct ast_frame *read_frame = NULL, *final_frame = NULL;
722 struct ast_format *slin;
723
724 /*
725 * Update the rate if compatibility mode is turned off or if it is
726 * turned on and the format rate is higher than the current rate.
727 *
728 * This makes it so any unnecessary rate switching/resetting does
729 * not take place and also any associated audiohook_list's internal
730 * sample rate maintains the highest sample rate between hooks.
731 */
732 if (!ast_test_flag(audiohook, AST_AUDIOHOOK_COMPATIBLE) ||
736 }
737
738 /* If the sample rate of the requested format differs from that of the underlying audiohook
739 * sample rate determine how many samples we actually need to get from the audiohook. This
740 * needs to occur as the signed linear factory stores them at the rate of the audiohook.
741 * We do this by determining the duration of audio they've requested and then determining
742 * how many samples that would be in the audiohook format.
743 */
744 if (ast_format_get_sample_rate(format) != audiohook->hook_internal_samp_rate) {
745 samples = (audiohook->hook_internal_samp_rate / 1000) * (samples / (ast_format_get_sample_rate(format) / 1000));
746 }
747
749 audiohook_read_frame_both(audiohook, samples, read_reference, write_reference) :
750 audiohook_read_frame_single(audiohook, samples, direction)))) {
751 return NULL;
752 }
753
755
756 /* If they don't want signed linear back out, we'll have to send it through the translation path */
757 if (ast_format_cmp(format, slin) != AST_FORMAT_CMP_EQUAL) {
758 /* Rebuild translation path if different format then previously */
759 if (ast_format_cmp(format, audiohook->format) == AST_FORMAT_CMP_NOT_EQUAL) {
760 if (audiohook->trans_pvt) {
762 audiohook->trans_pvt = NULL;
763 }
764
765 /* 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 */
766 if (!(audiohook->trans_pvt = ast_translator_build_path(format, slin))) {
768 return NULL;
769 }
770 ao2_replace(audiohook->format, format);
771 }
772 /* Convert to requested format, and allow the read in frame to be freed */
773 final_frame = ast_translate(audiohook->trans_pvt, read_frame, 1);
774 } else {
775 final_frame = read_frame;
776 }
777
778 return final_frame;
779}
static struct ast_frame * audiohook_read_frame_single(struct ast_audiohook *audiohook, size_t samples, enum ast_audiohook_direction direction)
Definition audiohook.c:521
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:555

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 521 of file audiohook.c.

522{
523 struct ast_slinfactory *factory = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook->read_factory : &audiohook->write_factory);
524 int vol = (direction == AST_AUDIOHOOK_DIRECTION_READ ? audiohook->options.read_volume : audiohook->options.write_volume);
525 short buf[samples];
526 struct ast_frame frame = {
528 .subclass.format = ast_format_cache_get_slin_by_rate(audiohook->hook_internal_samp_rate),
529 .data.ptr = buf,
530 .datalen = sizeof(buf),
531 .samples = samples,
532 };
533
534 /* Ensure the factory is able to give us the samples we want */
535 if (samples > ast_slinfactory_available(factory)) {
536 return NULL;
537 }
538
539 /* Read data in from factory */
540 if (!ast_slinfactory_read(factory, buf, samples)) {
541 return NULL;
542 }
543
544 if (SHOULD_MUTE(audiohook, direction)) {
545 /* Swap frame data for zeros if mute is required */
546 ast_frame_clear(&frame);
547 } else if (vol) {
548 /* If a volume adjustment needs to be applied apply it */
549 ast_frame_adjust_volume(&frame, vol);
550 }
551
552 return ast_frdup(&frame);
553}
#define SHOULD_MUTE(hook, dir)
Definition audiohook.c:460
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 368 of file audiohook.c.

369{
370 struct ast_format *slin;
371
372 if (audiohook->hook_internal_samp_rate == rate) {
373 return 0;
374 }
375
376 audiohook->hook_internal_samp_rate = rate;
377
379
380 /* Setup the factories that are needed for this audiohook type */
381 switch (audiohook->type) {
384 if (reset) {
387 }
390 break;
391 default:
392 break;
393 }
394
395 return 0;
396}
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 1587 of file audiohook.c.

1588{
1589 struct ast_datastore *datastore = NULL;
1591 float *gain = NULL;
1592
1593 /* If the audiohook is shutting down don't even bother */
1595 return 0;
1596 }
1597
1598 /* Try to find the datastore containing adjustment information, if we can't just bail out */
1599 if (!(datastore = ast_channel_datastore_find(chan, &audiohook_volume_datastore, NULL))) {
1600 return 0;
1601 }
1602
1603 audiohook_volume = datastore->data;
1604
1605 /* Based on direction grab the appropriate adjustment value */
1610 }
1611
1612 /* If an adjustment value is present modify the frame */
1613 if (gain && *gain) {
1614 ast_frame_adjust_volume_float(frame, *gain);
1615 }
1616
1617 return 0;
1618}
static const struct ast_datastore_info audiohook_volume_datastore
Datastore used to store audiohook volume information.
Definition audiohook.c:1574
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:2390
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:1552

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 1560 of file audiohook.c.

1561{
1562 struct audiohook_volume *audiohook_volume = data;
1563
1564 /* Destroy the audiohook as it is no longer in use */
1566
1567 /* Finally free ourselves, we are of no more use */
1569
1570 return;
1571}
int ast_audiohook_destroy(struct ast_audiohook *audiohook)
Destroys an audiohook structure.
Definition audiohook.c:422

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 1626 of file audiohook.c.

1627{
1628 struct ast_datastore *datastore = NULL;
1630
1631 /* If we are able to find the datastore return the contents (which is actually an audiohook_volume structure) */
1632 if ((datastore = ast_channel_datastore_find(chan, &audiohook_volume_datastore, NULL))) {
1633 return datastore->data;
1634 }
1635
1636 /* 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 */
1637 if (!create || !(datastore = ast_datastore_alloc(&audiohook_volume_datastore, NULL))) {
1638 return NULL;
1639 }
1640
1641 /* Create a new audiohook_volume structure to contain our adjustments and audiohook */
1642 if (!(audiohook_volume = ast_calloc(1, sizeof(*audiohook_volume)))) {
1643 ast_datastore_free(datastore);
1644 return NULL;
1645 }
1646
1647 /* Setup our audiohook structure so we can manipulate the audio */
1650
1651 /* Attach the audiohook_volume blob to the datastore and attach to the channel */
1652 datastore->data = audiohook_volume;
1653 ast_channel_datastore_add(chan, datastore);
1654
1655 /* All is well... put the audiohook into motion */
1657
1658 return audiohook_volume;
1659}
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:1587
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:398
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition channel.c:2376
#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 1115 of file audiohook.c.

1116{
1117 struct ast_audiohook *audiohook = NULL;
1118 int removed = 0;
1119
1120 AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->manipulate_list, audiohook, list) {
1121 ast_audiohook_lock(audiohook);
1122 if (audiohook->status != AST_AUDIOHOOK_STATUS_RUNNING) {
1124 removed = 1;
1126 ast_audiohook_unlock(audiohook);
1127 audiohook->manipulate_callback(audiohook, NULL, NULL, 0);
1128 if (ast_channel_is_bridged(chan)) {
1130 }
1131 continue;
1132 }
1133 if (ast_test_flag(audiohook, AST_AUDIOHOOK_WANTS_DTMF)) {
1134 audiohook->manipulate_callback(audiohook, chan, frame, direction);
1135 }
1136 ast_audiohook_unlock(audiohook);
1137 }
1139
1140 /* if an audiohook got removed, reset samplerate compatibility */
1141 if (removed) {
1143 }
1144 return frame;
1145}
@ 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 957 of file audiohook.c.

958{
959 struct ast_audiohook *audiohook = NULL;
960
961 AST_LIST_TRAVERSE(&audiohook_list->spy_list, audiohook, list) {
962 if (!strcasecmp(audiohook->source, source)) {
963 return audiohook;
964 }
965 }
966
967 AST_LIST_TRAVERSE(&audiohook_list->whisper_list, audiohook, list) {
968 if (!strcasecmp(audiohook->source, source)) {
969 return audiohook;
970 }
971 }
972
973 AST_LIST_TRAVERSE(&audiohook_list->manipulate_list, audiohook, list) {
974 if (!strcasecmp(audiohook->source, source)) {
975 return audiohook;
976 }
977 }
978
979 return NULL;
980}

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

◆ whisper_framehook_attach()

static int whisper_framehook_attach ( struct ast_channel *  chan,
struct ast_audiohook_list *  audiohook_list 
)
static

Definition at line 316 of file audiohook.c.

317{
318 struct ast_framehook_interface interface = {
320 .event_cb = whisper_framehook_event_cb,
321 .destroy_cb = whisper_framehook_destroy_cb,
322 .chan_fixup_cb = whisper_framehook_fixup,
323 .chan_breakdown_cb = whisper_framehook_breakdown,
324 };
325 struct whisper_framehook_data *hook_data;
326 int framehook_id;
327
328 if (audiohook_list->whisper_framehook_id >= 0) {
329 return 0;
330 }
331
332 hook_data = ast_calloc(1, sizeof(*hook_data));
333 if (!hook_data) {
334 return -1;
335 }
336 hook_data->timer_fd = -1;
337 hook_data->timer_fd_slot = -1;
339 whisper_framehook_timer_start(chan, hook_data);
340
341 interface.data = hook_data;
342 framehook_id = ast_framehook_attach(chan, &interface);
343 if (framehook_id < 0) {
344 whisper_framehook_timer_stop(chan, hook_data);
345 ast_free(hook_data);
346 return -1;
347 }
348
349 audiohook_list->whisper_framehook_id = framehook_id;
350 audiohook_list->whisper_framehook_data = hook_data;
351
352 return 0;
353}
static void whisper_framehook_timer_stop(struct ast_channel *chan, struct whisper_framehook_data *hook_data)
Definition audiohook.c:132
static void whisper_framehook_destroy_cb(void *data)
Definition audiohook.c:117
static void whisper_framehook_breakdown(void *data, int framehook_id, struct ast_channel *old_chan, struct ast_channel *new_chan)
Definition audiohook.c:195
static void whisper_framehook_timer_start(struct ast_channel *chan, struct whisper_framehook_data *hook_data)
Definition audiohook.c:144
#define AST_WHISPER_TIMER_INTERVAL
Definition audiohook.c:49
static struct ast_frame * whisper_framehook_event_cb(struct ast_channel *chan, struct ast_frame *frame, enum ast_framehook_event event, void *data)
Definition audiohook.c:216
static void whisper_framehook_fixup(void *data, int framehook_id, struct ast_channel *old_chan, struct ast_channel *new_chan)
Definition audiohook.c:180
int ast_framehook_attach(struct ast_channel *chan, struct ast_framehook_interface *i)
Attach an framehook onto a channel for frame interception.
Definition framehook.c:132
#define AST_FRAMEHOOK_INTERFACE_VERSION
Definition framehook.h:227
struct whisper_framehook_data * whisper_framehook_data
Definition audiohook.c:86

References ast_calloc, ast_framehook_attach(), AST_FRAMEHOOK_INTERFACE_VERSION, ast_free, AST_WHISPER_TIMER_INTERVAL, ast_framehook_interface::data, whisper_framehook_data::timer_fd, whisper_framehook_data::timer_fd_slot, whisper_framehook_data::timer_interval, ast_framehook_interface::version, whisper_framehook_breakdown(), ast_audiohook_list::whisper_framehook_data, whisper_framehook_destroy_cb(), whisper_framehook_event_cb(), whisper_framehook_fixup(), ast_audiohook_list::whisper_framehook_id, whisper_framehook_timer_start(), and whisper_framehook_timer_stop().

Referenced by ast_audiohook_attach().

◆ whisper_framehook_breakdown()

static void whisper_framehook_breakdown ( void *  data,
int  framehook_id,
struct ast_channel *  old_chan,
struct ast_channel *  new_chan 
)
static

Definition at line 195 of file audiohook.c.

197{
198 struct whisper_framehook_data *hook_data = data;
199
200 /* The destination's original descriptor array has been overwritten. */
201 if (!hook_data->timer) {
202 return;
203 }
204 hook_data->timer_fd_slot = ast_channel_fd_add(new_chan, hook_data->timer_fd);
205 if (hook_data->timer_fd_slot < 0) {
206 /*
207 * Keep the framehook attached so that the whisper audiohooks still
208 * have one.
209 */
210 whisper_framehook_timer_stop(new_chan, hook_data);
211 ast_log(LOG_WARNING, "Unable to register whisper timer on %s after masquerade\n",
212 ast_channel_name(new_chan));
213 }
214}
int ast_channel_fd_add(struct ast_channel *chan, int value)
Add a file descriptor to the channel without a fixed position.
struct ast_timer * timer
Definition audiohook.c:65

References ast_channel_fd_add(), ast_channel_name(), ast_log, LOG_WARNING, whisper_framehook_data::timer, whisper_framehook_data::timer_fd, whisper_framehook_data::timer_fd_slot, and whisper_framehook_timer_stop().

Referenced by whisper_framehook_attach().

◆ whisper_framehook_clear_fd()

static void whisper_framehook_clear_fd ( struct ast_channel *  chan,
struct whisper_framehook_data *  hook_data 
)
static

Definition at line 122 of file audiohook.c.

124{
125 /* A masquerade may have replaced this slot with another descriptor. */
126 if (hook_data->timer_fd_slot >= 0
127 && ast_channel_fd(chan, hook_data->timer_fd_slot) == hook_data->timer_fd) {
128 ast_channel_set_fd(chan, hook_data->timer_fd_slot, -1);
129 }
130}
int ast_channel_fd(const struct ast_channel *chan, int which)
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
Definition channel.c:2417

References ast_channel_fd(), ast_channel_set_fd(), whisper_framehook_data::timer_fd, and whisper_framehook_data::timer_fd_slot.

Referenced by whisper_framehook_fixup(), and whisper_framehook_timer_stop().

◆ whisper_framehook_destroy_cb()

static void whisper_framehook_destroy_cb ( void *  data)
static

Definition at line 117 of file audiohook.c.

118{
119 ast_free(data);
120}

References ast_free.

Referenced by whisper_framehook_attach().

◆ whisper_framehook_detach()

static void whisper_framehook_detach ( struct ast_channel *  chan,
struct ast_audiohook_list *  audiohook_list 
)
static

Definition at line 355 of file audiohook.c.

356{
357 if (audiohook_list->whisper_framehook_id < 0) {
358 return;
359 }
360
361 ast_framehook_detach(chan, audiohook_list->whisper_framehook_id);
362 /* Detachment is deferred, but the timer must stop before its slot is reused. */
364 audiohook_list->whisper_framehook_id = -1;
365 audiohook_list->whisper_framehook_data = NULL;
366}
int ast_framehook_detach(struct ast_channel *chan, int framehook_id)
Detach an framehook from a channel.
Definition framehook.c:177

References ast_framehook_detach(), NULL, ast_audiohook_list::whisper_framehook_data, ast_audiohook_list::whisper_framehook_id, and whisper_framehook_timer_stop().

Referenced by ast_audiohook_remove(), and audio_audiohook_write_list().

◆ whisper_framehook_event_cb()

static struct ast_frame * whisper_framehook_event_cb ( struct ast_channel *  chan,
struct ast_frame *  frame,
enum ast_framehook_event  event,
void *  data 
)
static

Definition at line 216 of file audiohook.c.

220{
221 struct whisper_framehook_data *hook_data = data;
222 struct ast_audiohook_list *audiohook_list;
223 int rate;
224 int samples;
226 struct ast_frame tmp_frame = {
228 .offset = AST_FRIENDLY_OFFSET,
229 .data.ptr = buf,
230 .datalen = sizeof(buf),
232 };
233 struct ast_frame *dup;
234
235 switch (event) {
237 /* We only care about timer driven READ events */
238 if (ast_channel_fdno(chan) != hook_data->timer_fd_slot
239 || !hook_data->timer
240 || ast_timer_ack(hook_data->timer, 1) < 0) {
241 return frame;
242 }
243 break;
245 /*
246 * Track WRITEs that are not triggered by the framehook so we can
247 * avoid overlapping with WRITEs that are triggered by the framehook.
248 */
249 if (frame && frame->frametype == AST_FRAME_VOICE
250 && (!frame->src || strcmp(frame->src, AST_WHISPER_TIMER_SRC))) {
251 hook_data->last_external_write_tv = ast_tvnow();
252 }
253 return frame;
255 return frame;
257 whisper_framehook_stop(chan, hook_data);
258 return frame;
259 }
260
261 /*
262 * If normal outbound media frames are actively flowing (determined by tracking the
263 * WRITE events above,) skip timer-based fallback injection. This avoids overlapping
264 * WRITE frames and the resulting garbled audio.
265 */
266 if (!ast_tvzero(hook_data->last_external_write_tv)
268 <= (hook_data->timer_interval * 2)) {
269 return frame;
270 }
271
272 audiohook_list = ast_channel_audiohooks(chan);
273
274 /*
275 * As this framehook is dependant on the whisper audiohook(s) existing, this check
276 * should never fail.
277 */
278 if (!audiohook_list || AST_LIST_EMPTY(&audiohook_list->whisper_list)) {
279 return frame;
280 }
281
282 rate = audiohook_list->list_internal_samp_rate;
283 if (rate <= 0) {
285 }
286 samples = (rate / 1000) * hook_data->timer_interval;
287 if (!samples || samples > ARRAY_LEN(buf)) {
288 return frame;
289 }
290
291 memset(buf, 0, samples * sizeof(buf[0]));
293 tmp_frame.samples = samples;
294 tmp_frame.datalen = samples * sizeof(buf[0]);
295
296 dup = ast_frdup(&tmp_frame);
297 if (!dup) {
298 return frame;
299 }
300
301 /*
302 * Invoke a write on the channel with our frame to trigger mixing in
303 * audio from the whisper audiohook list.
304 */
305 ast_channel_unlock(chan);
306 ast_write(chan, dup);
307 ast_channel_lock(chan);
308
309 /* ast_write does not consume the frame, even when the write succeeds. */
310 ast_frfree(dup);
311
312 /* The timer may have coincided with a queued media or control frame. */
313 return frame;
314}
#define AST_WHISPER_TIMER_SRC
Definition audiohook.c:55
static void whisper_framehook_stop(struct ast_channel *chan, struct whisper_framehook_data *hook_data)
Definition audiohook.c:167
int ast_channel_fdno(const struct ast_channel *chan)
int ast_write(struct ast_channel *chan, struct ast_frame *frame)
Write a frame to a channel This function writes the given frame to the indicated channel.
Definition channel.c:5167
@ AST_FRAMEHOOK_EVENT_ATTACHED
Definition framehook.h:154
@ AST_FRAMEHOOK_EVENT_DETACHED
Definition framehook.h:155
@ AST_FRAMEHOOK_EVENT_WRITE
Definition framehook.h:153
@ AST_FRAMEHOOK_EVENT_READ
Definition framehook.h:152
#define AST_FRIENDLY_OFFSET
Offset into a frame's data buffer.
struct timeval last_external_write_tv
Definition audiohook.c:69
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition time.h:117
int ast_timer_ack(const struct ast_timer *handle, unsigned int quantity)
Acknowledge a timer event.
Definition timing.c:171
#define ARRAY_LEN(a)
Definition utils.h:706

References ARRAY_LEN, ast_channel_audiohooks(), ast_channel_fdno(), ast_channel_lock, ast_channel_unlock, ast_format_cache_get_slin_by_rate(), AST_FRAME_VOICE, AST_FRAMEHOOK_EVENT_ATTACHED, AST_FRAMEHOOK_EVENT_DETACHED, AST_FRAMEHOOK_EVENT_READ, AST_FRAMEHOOK_EVENT_WRITE, ast_frdup, ast_frfree, AST_FRIENDLY_OFFSET, AST_LIST_EMPTY, ast_timer_ack(), ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), AST_WHISPER_TIMER_INTERVAL_MAX, AST_WHISPER_TIMER_SRC, ast_write(), buf, ast_frame::datalen, DEFAULT_INTERNAL_SAMPLE_RATE, ast_frame_subclass::format, ast_frame::frametype, whisper_framehook_data::last_external_write_tv, ast_audiohook_list::list_internal_samp_rate, ast_frame::samples, ast_frame::src, ast_frame::subclass, whisper_framehook_data::timer, whisper_framehook_data::timer_fd_slot, whisper_framehook_data::timer_interval, whisper_framehook_stop(), and ast_audiohook_list::whisper_list.

Referenced by whisper_framehook_attach().

◆ whisper_framehook_fixup()

static void whisper_framehook_fixup ( void *  data,
int  framehook_id,
struct ast_channel *  old_chan,
struct ast_channel *  new_chan 
)
static

Definition at line 180 of file audiohook.c.

182{
183 struct whisper_framehook_data *hook_data = data;
184
185 /*
186 * The descriptors have already been copied, but the audiohooks have not
187 * moved yet. Retire this inherited framehook on both channels. Moving the
188 * audiohooks will attach a new one if the destination needs it.
189 */
190 whisper_framehook_clear_fd(new_chan, hook_data);
191 whisper_framehook_stop(old_chan, hook_data);
192 ast_framehook_detach(new_chan, framehook_id);
193}
static void whisper_framehook_clear_fd(struct ast_channel *chan, struct whisper_framehook_data *hook_data)
Definition audiohook.c:122

References ast_framehook_detach(), whisper_framehook_clear_fd(), and whisper_framehook_stop().

Referenced by whisper_framehook_attach().

◆ whisper_framehook_stop()

static void whisper_framehook_stop ( struct ast_channel *  chan,
struct whisper_framehook_data *  hook_data 
)
static

Definition at line 167 of file audiohook.c.

169{
170 struct ast_audiohook_list *audiohook_list = ast_channel_audiohooks(chan);
171
172 whisper_framehook_timer_stop(chan, hook_data);
173 /* Only remove the framehook if the channel's list still refers to it. */
174 if (audiohook_list && audiohook_list->whisper_framehook_data == hook_data) {
175 audiohook_list->whisper_framehook_id = -1;
176 audiohook_list->whisper_framehook_data = NULL;
177 }
178}

References ast_channel_audiohooks(), NULL, ast_audiohook_list::whisper_framehook_data, ast_audiohook_list::whisper_framehook_id, and whisper_framehook_timer_stop().

Referenced by whisper_framehook_event_cb(), and whisper_framehook_fixup().

◆ whisper_framehook_timer_start()

static void whisper_framehook_timer_start ( struct ast_channel *  chan,
struct whisper_framehook_data *  hook_data 
)
static

Definition at line 144 of file audiohook.c.

146{
147 /*
148 * The timer is optional. Without it, whisper audio is still mixed into
149 * outbound media, but nothing is sent while the channel has none.
150 */
151 hook_data->timer = ast_timer_open();
152 if (!hook_data->timer) {
153 ast_log(LOG_WARNING, "Unable to open whisper timer on %s\n",
154 ast_channel_name(chan));
155 return;
156 }
157 hook_data->timer_fd = ast_timer_fd(hook_data->timer);
158 hook_data->timer_fd_slot = ast_channel_fd_add(chan, hook_data->timer_fd);
159 if (hook_data->timer_fd_slot < 0
160 || ast_timer_set_rate(hook_data->timer, 1000 / hook_data->timer_interval)) {
161 whisper_framehook_timer_stop(chan, hook_data);
162 ast_log(LOG_WARNING, "Unable to start whisper timer on %s\n",
163 ast_channel_name(chan));
164 }
165}
int ast_timer_set_rate(const struct ast_timer *handle, unsigned int rate)
Set the timing tick rate.
Definition timing.c:166
struct ast_timer * ast_timer_open(void)
Open a timer.
Definition timing.c:122
int ast_timer_fd(const struct ast_timer *handle)
Get a poll()-able file descriptor for a timer.
Definition timing.c:161

References ast_channel_fd_add(), ast_channel_name(), ast_log, ast_timer_fd(), ast_timer_open(), ast_timer_set_rate(), LOG_WARNING, whisper_framehook_data::timer, whisper_framehook_data::timer_fd, whisper_framehook_data::timer_fd_slot, whisper_framehook_data::timer_interval, and whisper_framehook_timer_stop().

Referenced by whisper_framehook_attach().

◆ whisper_framehook_timer_stop()

static void whisper_framehook_timer_stop ( struct ast_channel *  chan,
struct whisper_framehook_data *  hook_data 
)
static

Definition at line 132 of file audiohook.c.

134{
135 whisper_framehook_clear_fd(chan, hook_data);
136 if (hook_data->timer) {
137 ast_timer_close(hook_data->timer);
138 hook_data->timer = NULL;
139 }
140 hook_data->timer_fd = -1;
141 hook_data->timer_fd_slot = -1;
142}
void ast_timer_close(struct ast_timer *handle)
Close an opened timing handle.
Definition timing.c:154

References ast_timer_close(), NULL, whisper_framehook_data::timer, whisper_framehook_data::timer_fd, whisper_framehook_data::timer_fd_slot, and whisper_framehook_clear_fd().

Referenced by whisper_framehook_attach(), whisper_framehook_breakdown(), whisper_framehook_detach(), whisper_framehook_stop(), and whisper_framehook_timer_start().

◆ whisper_framehook_timer_update()

static void whisper_framehook_timer_update ( struct ast_audiohook_list *  audiohook_list,
struct ast_frame *  start_frame,
int  internal_sample_rate,
int  samples 
)
static

Definition at line 89 of file audiohook.c.

93{
94 struct whisper_framehook_data *hook_data;
95 int interval;
96
97 hook_data = audiohook_list->whisper_framehook_data;
98 if (!hook_data || internal_sample_rate <= 0 || samples <= 0) {
99 return;
100 }
101
102 if (start_frame->src && !strcmp(start_frame->src, AST_WHISPER_TIMER_SRC)) {
103 return;
104 }
105
106 interval = AST_WHISPER_TIMER_CLAMP((samples * 1000) / internal_sample_rate);
107 if (interval == hook_data->timer_interval) {
108 return;
109 }
110
111 hook_data->timer_interval = interval;
112 if (hook_data->timer) {
113 ast_timer_set_rate(hook_data->timer, 1000 / interval);
114 }
115}
#define AST_WHISPER_TIMER_CLAMP(interval)
Definition audiohook.c:52

References ast_timer_set_rate(), AST_WHISPER_TIMER_CLAMP, AST_WHISPER_TIMER_SRC, ast_frame::src, whisper_framehook_data::timer, whisper_framehook_data::timer_interval, and ast_audiohook_list::whisper_framehook_data.

Referenced by audio_audiohook_write_list().

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:1560

Datastore used to store audiohook volume information.

Definition at line 1574 of file audiohook.c.

1574 {
1575 .type = "Volume",
1576 .destroy = audiohook_volume_destroy,
1577};

Referenced by audiohook_volume_callback(), and audiohook_volume_get().