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/linkedlists.h"
#include "asterisk/audiohook.h"
#include "asterisk/slinfactory.h"
#include "asterisk/frame.h"
#include "asterisk/translate.h"
#include "asterisk/format_cache.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...

Defines

#define AST_AUDIOHOOK_SMALL_QUEUE_TOLERANCE   100
#define AST_AUDIOHOOK_SYNC_TOLERANCE   100

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_frameast_audiohook_read_frame (struct ast_audiohook *audiohook, size_t samples, enum ast_audiohook_direction direction, struct ast_format *format)
 Reads a frame in from the audiohook structure.
struct ast_frameast_audiohook_read_frame_all (struct ast_audiohook *audiohook, size_t samples, struct ast_format *format, struct ast_frame **read_frame, struct ast_frame **write_frame)
 Reads a frame in from the audiohook structure.
int ast_audiohook_remove (struct ast_channel *chan, struct ast_audiohook *audiohook)
 Remove an audiohook from a specified channel.
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.
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_get (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_write_frame (struct ast_audiohook *audiohook, enum ast_audiohook_direction direction, struct ast_frame *frame)
 Writes a frame into the audiohook structure.
struct ast_frameast_audiohook_write_list (struct ast_channel *chan, struct ast_audiohook_list *audiohook_list, enum ast_audiohook_direction direction, struct ast_frame *frame)
 Pass a frame off to be handled by the audiohook core.
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_frameaudio_audiohook_write_list (struct ast_channel *chan, struct ast_audiohook_list *audiohook_list, enum ast_audiohook_direction direction, struct ast_frame *frame)
 Pass an AUDIO frame off to be handled by the audiohook core.
static void audiohook_list_set_samplerate_compatibility (struct ast_audiohook_list *audiohook_list)
static struct ast_frameaudiohook_list_translate_to_native (struct ast_audiohook_list *audiohook_list, enum ast_audiohook_direction direction, struct ast_frame *slin_frame, struct ast_format *outformat)
static struct ast_frameaudiohook_list_translate_to_slin (struct ast_audiohook_list *audiohook_list, enum ast_audiohook_direction direction, struct ast_frame *frame)
static void audiohook_move (struct ast_channel *old_chan, struct ast_channel *new_chan, struct ast_audiohook *audiohook)
static struct ast_frameaudiohook_read_frame_both (struct ast_audiohook *audiohook, size_t samples, struct ast_frame **read_reference, struct ast_frame **write_reference)
static struct ast_frameaudiohook_read_frame_helper (struct ast_audiohook *audiohook, size_t samples, enum ast_audiohook_direction direction, struct ast_format *format, struct ast_frame **read_reference, struct ast_frame **write_reference)
static struct ast_frameaudiohook_read_frame_single (struct ast_audiohook *audiohook, size_t samples, enum ast_audiohook_direction direction)
static int audiohook_set_internal_rate (struct ast_audiohook *audiohook, int rate, int reset)
static int audiohook_volume_callback (struct ast_audiohook *audiohook, struct ast_channel *chan, struct ast_frame *frame, enum ast_audiohook_direction direction)
 Helper function which actually gets called by audiohooks to perform the adjustment.
static void audiohook_volume_destroy (void *data)
 Callback used to destroy the audiohook volume datastore.
static struct audiohook_volumeaudiohook_volume_get (struct ast_channel *chan, int create)
 Helper function which finds and optionally creates an audiohook_volume_datastore datastore on a channel.
static struct ast_framedtmf_audiohook_write_list (struct ast_channel *chan, struct ast_audiohook_list *audiohook_list, enum ast_audiohook_direction direction, struct ast_frame *frame)
 Pass a DTMF frame off to be handled by the audiohook core.
static struct ast_audiohookfind_audiohook_by_source (struct ast_audiohook_list *audiohook_list, const char *source)
 find an audiohook based on its source

Variables

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


Detailed Description

Audiohooks Architecture.

Author:
Joshua Colp <jcolp@digium.com>

Definition in file audiohook.c.


Define Documentation

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

Referenced by ast_audiohook_write_frame().

#define AST_AUDIOHOOK_SYNC_TOLERANCE   100

Tolerance in milliseconds for audiohooks synchronization

Definition at line 46 of file audiohook.c.

Referenced by ast_audiohook_write_frame().


Function Documentation

int ast_audiohook_attach ( struct ast_channel chan,
struct ast_audiohook audiohook 
)

Attach audiohook to channel.

Parameters:
chan Channel
audiohook Audiohook structure
Returns:
Returns 0 on success, -1 on failure

Definition at line 442 of file audiohook.c.

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_is_bridged(), ast_channel_lock, ast_channel_set_unbridged_nolock(), ast_channel_unlock, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_TAIL, audiohook_list_set_samplerate_compatibility(), audiohook_set_internal_rate(), ast_audiohook_list::list_internal_samp_rate, ast_audiohook_list::manipulate_list, ast_audiohook_list::spy_list, ast_audiohook::type, and ast_audiohook_list::whisper_list.

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

00443 {
00444    ast_channel_lock(chan);
00445 
00446    if (!ast_channel_audiohooks(chan)) {
00447       struct ast_audiohook_list *ahlist;
00448       /* Whoops... allocate a new structure */
00449       if (!(ahlist = ast_calloc(1, sizeof(*ahlist)))) {
00450          ast_channel_unlock(chan);
00451          return -1;
00452       }
00453       ast_channel_audiohooks_set(chan, ahlist);
00454       AST_LIST_HEAD_INIT_NOLOCK(&ast_channel_audiohooks(chan)->spy_list);
00455       AST_LIST_HEAD_INIT_NOLOCK(&ast_channel_audiohooks(chan)->whisper_list);
00456       AST_LIST_HEAD_INIT_NOLOCK(&ast_channel_audiohooks(chan)->manipulate_list);
00457       /* This sample rate will adjust as necessary when writing to the list. */
00458       ast_channel_audiohooks(chan)->list_internal_samp_rate = 8000;
00459    }
00460 
00461    /* Drop into respective list */
00462    if (audiohook->type == AST_AUDIOHOOK_TYPE_SPY) {
00463       AST_LIST_INSERT_TAIL(&ast_channel_audiohooks(chan)->spy_list, audiohook, list);
00464    } else if (audiohook->type == AST_AUDIOHOOK_TYPE_WHISPER) {
00465       AST_LIST_INSERT_TAIL(&ast_channel_audiohooks(chan)->whisper_list, audiohook, list);
00466    } else if (audiohook->type == AST_AUDIOHOOK_TYPE_MANIPULATE) {
00467       AST_LIST_INSERT_TAIL(&ast_channel_audiohooks(chan)->manipulate_list, audiohook, list);
00468    }
00469 
00470 
00471    audiohook_set_internal_rate(audiohook, ast_channel_audiohooks(chan)->list_internal_samp_rate, 1);
00472    audiohook_list_set_samplerate_compatibility(ast_channel_audiohooks(chan));
00473 
00474    /* Change status over to running since it is now attached */
00475    ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_RUNNING);
00476 
00477    if (ast_channel_is_bridged(chan)) {
00478       ast_channel_set_unbridged_nolock(chan, 1);
00479    }
00480 
00481    ast_channel_unlock(chan);
00482 
00483    return 0;
00484 }

int ast_audiohook_destroy ( struct ast_audiohook audiohook  ) 

Destroys an audiohook structure.

Parameters:
audiohook Audiohook structure
Returns:
Returns 0 on success, -1 on failure

Definition at line 132 of file audiohook.c.

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

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

00133 {
00134    /* Drop the factories used by this audiohook type */
00135    switch (audiohook->type) {
00136    case AST_AUDIOHOOK_TYPE_SPY:
00137    case AST_AUDIOHOOK_TYPE_WHISPER:
00138       ast_slinfactory_destroy(&audiohook->read_factory);
00139       ast_slinfactory_destroy(&audiohook->write_factory);
00140       break;
00141    default:
00142       break;
00143    }
00144 
00145    /* Destroy translation path if present */
00146    if (audiohook->trans_pvt)
00147       ast_translator_free_path(audiohook->trans_pvt);
00148 
00149    ao2_cleanup(audiohook->format);
00150 
00151    /* Lock and trigger be gone! */
00152    ast_cond_destroy(&audiohook->trigger);
00153    ast_mutex_destroy(&audiohook->lock);
00154 
00155    return 0;
00156 }

int ast_audiohook_detach ( struct ast_audiohook audiohook  ) 

Detach audiohook from channel.

Parameters:
audiohook Audiohook structure
Returns:
Returns 0 on success, -1 on failure

Definition at line 508 of file audiohook.c.

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

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

00509 {
00510    if (audiohook->status == AST_AUDIOHOOK_STATUS_NEW || audiohook->status == AST_AUDIOHOOK_STATUS_DONE) {
00511       return 0;
00512    }
00513 
00514    ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_SHUTDOWN);
00515 
00516    while (audiohook->status != AST_AUDIOHOOK_STATUS_DONE) {
00517       ast_audiohook_trigger_wait(audiohook);
00518    }
00519 
00520    return 0;
00521 }

void ast_audiohook_detach_list ( struct ast_audiohook_list audiohook_list  ) 

Detach audiohooks from list and destroy said list.

Parameters:
audiohook_list List of audiohooks (NULL tolerant)
Returns:
Nothing

Definition at line 523 of file audiohook.c.

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

00524 {
00525    int i;
00526    struct ast_audiohook *audiohook;
00527 
00528    if (!audiohook_list) {
00529       return;
00530    }
00531 
00532    /* Drop any spies */
00533    while ((audiohook = AST_LIST_REMOVE_HEAD(&audiohook_list->spy_list, list))) {
00534       ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_DONE);
00535    }
00536 
00537    /* Drop any whispering sources */
00538    while ((audiohook = AST_LIST_REMOVE_HEAD(&audiohook_list->whisper_list, list))) {
00539       ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_DONE);
00540    }
00541 
00542    /* Drop any manipulaters */
00543    while ((audiohook = AST_LIST_REMOVE_HEAD(&audiohook_list->manipulate_list, list))) {
00544       ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_DONE);
00545       audiohook->manipulate_callback(audiohook, NULL, NULL, 0);
00546    }
00547 
00548    /* Drop translation paths if present */
00549    for (i = 0; i < 2; i++) {
00550       if (audiohook_list->in_translate[i].trans_pvt) {
00551          ast_translator_free_path(audiohook_list->in_translate[i].trans_pvt);
00552          ao2_cleanup(audiohook_list->in_translate[i].format);
00553       }
00554       if (audiohook_list->out_translate[i].trans_pvt) {
00555          ast_translator_free_path(audiohook_list->out_translate[i].trans_pvt);
00556          ao2_cleanup(audiohook_list->in_translate[i].format);
00557       }
00558    }
00559 
00560    /* Free ourselves */
00561    ast_free(audiohook_list);
00562 }

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

Detach specified source audiohook from channel.

Parameters:
chan Channel to detach from
source Name of source to detach
Returns:
Returns 0 on success, -1 on failure

Definition at line 660 of file audiohook.c.

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, and ast_audiohook::status.

00661 {
00662    struct ast_audiohook *audiohook = NULL;
00663 
00664    ast_channel_lock(chan);
00665 
00666    /* Ensure the channel has audiohooks on it */
00667    if (!ast_channel_audiohooks(chan)) {
00668       ast_channel_unlock(chan);
00669       return -1;
00670    }
00671 
00672    audiohook = find_audiohook_by_source(ast_channel_audiohooks(chan), source);
00673 
00674    ast_channel_unlock(chan);
00675 
00676    if (audiohook && audiohook->status != AST_AUDIOHOOK_STATUS_DONE) {
00677       ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_SHUTDOWN);
00678    }
00679 
00680    return (audiohook ? 0 : -1);
00681 }

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.

Parameters:
audiohook Audiohook structure
type 
source,init_flags 
Returns:
Returns 0 on success, -1 on failure

Definition at line 107 of file audiohook.c.

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

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

00108 {
00109    /* Need to keep the type and source */
00110    audiohook->type = type;
00111    audiohook->source = source;
00112 
00113    /* Initialize lock that protects our audiohook */
00114    ast_mutex_init(&audiohook->lock);
00115    ast_cond_init(&audiohook->trigger, NULL);
00116 
00117    audiohook->init_flags = init_flags;
00118 
00119    /* initialize internal rate at 8khz, this will adjust if necessary */
00120    audiohook_set_internal_rate(audiohook, 8000, 0);
00121 
00122    /* Since we are just starting out... this audiohook is new */
00123    ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_NEW);
00124 
00125    return 0;
00126 }

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_chan The source of the audiohooks being moved
new_chan The destination channel for the audiohooks to be moved to

Definition at line 629 of file audiohook.c.

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

00630 {
00631    struct ast_audiohook *audiohook;
00632    struct ast_audiohook_list *audiohook_list;
00633 
00634    audiohook_list = ast_channel_audiohooks(old_chan);
00635    if (!audiohook_list) {
00636       return;
00637    }
00638 
00639    AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->spy_list, audiohook, list) {
00640       audiohook_move(old_chan, new_chan, audiohook);
00641    }
00642    AST_LIST_TRAVERSE_SAFE_END;
00643 
00644    AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->whisper_list, audiohook, list) {
00645       audiohook_move(old_chan, new_chan, audiohook);
00646    }
00647    AST_LIST_TRAVERSE_SAFE_END;
00648 
00649    AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->manipulate_list, audiohook, list) {
00650       audiohook_move(old_chan, new_chan, audiohook);
00651    }
00652    AST_LIST_TRAVERSE_SAFE_END;
00653 }

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_chan The source of the audiohook to move
new_chan The destination to which we want the audiohook to move
source The source of the audiohook we want to move

Definition at line 613 of file audiohook.c.

References ast_channel_audiohooks(), audiohook_move(), and find_audiohook_by_source().

00614 {
00615    struct ast_audiohook *audiohook;
00616 
00617    if (!ast_channel_audiohooks(old_chan)) {
00618       return;
00619    }
00620 
00621    audiohook = find_audiohook_by_source(ast_channel_audiohooks(old_chan), source);
00622    if (!audiohook) {
00623       return;
00624    }
00625 
00626    audiohook_move(old_chan, new_chan, audiohook);
00627 }

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

Reads a frame in from the audiohook structure.

Parameters:
audiohook Audiohook structure
samples Number of samples wanted in requested output format
direction Direction the audio frame came from
format Format of frame remote side wants back
Returns:
Returns frame on success, NULL on failure

Definition at line 406 of file audiohook.c.

References audiohook_read_frame_helper(), and NULL.

Referenced by snoop_read(), and spy_generate().

00407 {
00408    return audiohook_read_frame_helper(audiohook, samples, direction, format, NULL, NULL);
00409 }

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 
) [read]

Reads a frame in from the audiohook structure.

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

Parameters:
audiohook Audiohook structure
samples Number of samples wanted
direction Direction the audio frame came from
format Format of frame remote side wants back
read_frame frame pointer for copying read frame data
write_frame frame pointer for copying write frame data
Returns:
Returns frame on success, NULL on failure

Definition at line 420 of file audiohook.c.

References AST_AUDIOHOOK_DIRECTION_BOTH, and audiohook_read_frame_helper().

Referenced by mixmonitor_thread().

00421 {
00422    return audiohook_read_frame_helper(audiohook, samples, AST_AUDIOHOOK_DIRECTION_BOTH, format, read_frame, write_frame);
00423 }

int ast_audiohook_remove ( struct ast_channel chan,
struct ast_audiohook audiohook 
)

Remove an audiohook from a specified channel.

Parameters:
chan Channel to remove from
audiohook Audiohook to remove
Returns:
Returns 0 on success, -1 on failure
Note:
The channel does not need to be locked before calling this function

Definition at line 693 of file audiohook.c.

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

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

00694 {
00695    ast_channel_lock(chan);
00696 
00697    if (!ast_channel_audiohooks(chan)) {
00698       ast_channel_unlock(chan);
00699       return -1;
00700    }
00701 
00702    if (audiohook->type == AST_AUDIOHOOK_TYPE_SPY) {
00703       AST_LIST_REMOVE(&ast_channel_audiohooks(chan)->spy_list, audiohook, list);
00704    } else if (audiohook->type == AST_AUDIOHOOK_TYPE_WHISPER) {
00705       AST_LIST_REMOVE(&ast_channel_audiohooks(chan)->whisper_list, audiohook, list);
00706    } else if (audiohook->type == AST_AUDIOHOOK_TYPE_MANIPULATE) {
00707       AST_LIST_REMOVE(&ast_channel_audiohooks(chan)->manipulate_list, audiohook, list);
00708    }
00709 
00710    audiohook_list_set_samplerate_compatibility(ast_channel_audiohooks(chan));
00711    ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_DONE);
00712 
00713    if (ast_channel_is_bridged(chan)) {
00714       ast_channel_set_unbridged_nolock(chan, 1);
00715    }
00716 
00717    ast_channel_unlock(chan);
00718 
00719    return 0;
00720 }

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:
chan Channel to muck with
source Type of audiohook
flag which flag to set / clear
clear set or clear
Returns:
Returns 0 on success, -1 on failure

Definition at line 1280 of file audiohook.c.

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

Referenced by manager_mute_mixmonitor().

01281 {
01282    struct ast_audiohook *audiohook = NULL;
01283 
01284    ast_channel_lock(chan);
01285 
01286    /* Ensure the channel has audiohooks on it */
01287    if (!ast_channel_audiohooks(chan)) {
01288       ast_channel_unlock(chan);
01289       return -1;
01290    }
01291 
01292    audiohook = find_audiohook_by_source(ast_channel_audiohooks(chan), source);
01293 
01294    if (audiohook) {
01295       if (clear) {
01296          ast_clear_flag(audiohook, flag);
01297       } else {
01298          ast_set_flag(audiohook, flag);
01299       }
01300    }
01301 
01302    ast_channel_unlock(chan);
01303 
01304    return (audiohook ? 0 : -1);
01305 }

void ast_audiohook_trigger_wait ( struct ast_audiohook audiohook  ) 

Wait for audiohook trigger to be triggered.

Parameters:
audiohook Audiohook to wait on

Definition at line 998 of file audiohook.c.

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

00999 {
01000    struct timeval wait;
01001    struct timespec ts;
01002 
01003    wait = ast_tvadd(ast_tvnow(), ast_samp2tv(50000, 1000));
01004    ts.tv_sec = wait.tv_sec;
01005    ts.tv_nsec = wait.tv_usec * 1000;
01006 
01007    ast_cond_timedwait(&audiohook->trigger, &audiohook->lock, &ts);
01008 
01009    return;
01010 }

void ast_audiohook_update_status ( struct ast_audiohook audiohook,
enum ast_audiohook_status  status 
)

Update audiohook's status.

Parameters:
audiohook Audiohook structure
status Audiohook status enum
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 494 of file audiohook.c.

References ast_audiohook_lock, AST_AUDIOHOOK_STATUS_DONE, ast_audiohook_unlock, ast_cond_signal, 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().

00495 {
00496    ast_audiohook_lock(audiohook);
00497    if (audiohook->status != AST_AUDIOHOOK_STATUS_DONE) {
00498       audiohook->status = status;
00499       ast_cond_signal(&audiohook->trigger);
00500    }
00501    ast_audiohook_unlock(audiohook);
00502 }

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:
chan Channel to muck with
direction Direction to increase
volume Value to adjust the adjustment by
Returns:
Returns 0 on success, -1 on failure

Definition at line 1253 of file audiohook.c.

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

01254 {
01255    struct audiohook_volume *audiohook_volume = NULL;
01256 
01257    /* Attempt to find the audiohook volume information, and create an audiohook if none exists */
01258    if (!(audiohook_volume = audiohook_volume_get(chan, 1))) {
01259       return -1;
01260    }
01261 
01262    /* Based on the direction change the specific adjustment value */
01263    if (direction == AST_AUDIOHOOK_DIRECTION_READ || direction == AST_AUDIOHOOK_DIRECTION_BOTH) {
01264       audiohook_volume->read_adjustment += volume;
01265    }
01266    if (direction == AST_AUDIOHOOK_DIRECTION_WRITE || direction == AST_AUDIOHOOK_DIRECTION_BOTH) {
01267       audiohook_volume->write_adjustment += volume;
01268    }
01269 
01270    return 0;
01271 }

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:
chan Channel to retrieve volume adjustment from
direction Direction to retrieve
Returns:
Returns adjustment value

Definition at line 1227 of file audiohook.c.

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

Referenced by confbridge_exec().

01228 {
01229    struct audiohook_volume *audiohook_volume = NULL;
01230    int adjustment = 0;
01231 
01232    /* Attempt to find the audiohook volume information, but do not create it as we only want to look at the values */
01233    if (!(audiohook_volume = audiohook_volume_get(chan, 0))) {
01234       return 0;
01235    }
01236 
01237    /* Grab the adjustment value based on direction given */
01238    if (direction == AST_AUDIOHOOK_DIRECTION_READ) {
01239       adjustment = audiohook_volume->read_adjustment;
01240    } else if (direction == AST_AUDIOHOOK_DIRECTION_WRITE) {
01241       adjustment = audiohook_volume->write_adjustment;
01242    }
01243 
01244    return adjustment;
01245 }

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:
chan Channel to muck with
direction Direction to set on
volume Value to adjust the volume by
Returns:
Returns 0 on success, -1 on failure

Definition at line 1202 of file audiohook.c.

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 confbridge_exec(), and execute_menu_entry().

01203 {
01204    struct audiohook_volume *audiohook_volume = NULL;
01205 
01206    /* Attempt to find the audiohook volume information, but only create it if we are not setting the adjustment value to zero */
01207    if (!(audiohook_volume = audiohook_volume_get(chan, (volume ? 1 : 0)))) {
01208       return -1;
01209    }
01210 
01211    /* Now based on the direction set the proper value */
01212    if (direction == AST_AUDIOHOOK_DIRECTION_READ || direction == AST_AUDIOHOOK_DIRECTION_BOTH) {
01213       audiohook_volume->read_adjustment = volume;
01214    }
01215    if (direction == AST_AUDIOHOOK_DIRECTION_WRITE || direction == AST_AUDIOHOOK_DIRECTION_BOTH) {
01216       audiohook_volume->write_adjustment = volume;
01217    }
01218 
01219    return 0;
01220 }

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 Audiohook structure
direction Direction the audio frame came from
frame Frame to write in
Returns:
Returns 0 on success, -1 on failure

Definition at line 164 of file audiohook.c.

References AST_AUDIOHOOK_DIRECTION_READ, AST_AUDIOHOOK_DIRECTION_WRITE, AST_AUDIOHOOK_MUTE_READ, AST_AUDIOHOOK_MUTE_WRITE, 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_frame_clear(), ast_slinfactory_available(), ast_slinfactory_feed(), ast_slinfactory_flush(), ast_test_flag, ast_tvdiff_ms(), ast_tvnow(), ast_frame::datalen, 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(), and snoop_write().

00165 {
00166    struct ast_slinfactory *factory = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook->read_factory : &audiohook->write_factory);
00167    struct ast_slinfactory *other_factory = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook->write_factory : &audiohook->read_factory);
00168    struct timeval *rwtime = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook->read_time : &audiohook->write_time), previous_time = *rwtime;
00169    int our_factory_samples;
00170    int our_factory_ms;
00171    int other_factory_samples;
00172    int other_factory_ms;
00173    int muteme = 0;
00174 
00175    /* Update last feeding time to be current */
00176    *rwtime = ast_tvnow();
00177 
00178    our_factory_samples = ast_slinfactory_available(factory);
00179    our_factory_ms = ast_tvdiff_ms(*rwtime, previous_time) + (our_factory_samples / (audiohook->hook_internal_samp_rate / 1000));
00180    other_factory_samples = ast_slinfactory_available(other_factory);
00181    other_factory_ms = other_factory_samples / (audiohook->hook_internal_samp_rate / 1000);
00182 
00183    if (ast_test_flag(audiohook, AST_AUDIOHOOK_TRIGGER_SYNC) && other_factory_samples && (our_factory_ms - other_factory_ms > AST_AUDIOHOOK_SYNC_TOLERANCE)) {
00184       ast_debug(1, "Flushing audiohook %p so it remains in sync\n", audiohook);
00185       ast_slinfactory_flush(factory);
00186       ast_slinfactory_flush(other_factory);
00187    }
00188 
00189    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))) {
00190       ast_debug(1, "Audiohook %p has stale audio in its factories. Flushing them both\n", audiohook);
00191       ast_slinfactory_flush(factory);
00192       ast_slinfactory_flush(other_factory);
00193    }
00194 
00195    /* swap frame data for zeros if mute is required */
00196    if ((ast_test_flag(audiohook, AST_AUDIOHOOK_MUTE_READ) && (direction == AST_AUDIOHOOK_DIRECTION_READ)) ||
00197       (ast_test_flag(audiohook, AST_AUDIOHOOK_MUTE_WRITE) && (direction == AST_AUDIOHOOK_DIRECTION_WRITE)) ||
00198       (ast_test_flag(audiohook, AST_AUDIOHOOK_MUTE_READ | AST_AUDIOHOOK_MUTE_WRITE) == (AST_AUDIOHOOK_MUTE_READ | AST_AUDIOHOOK_MUTE_WRITE))) {
00199          muteme = 1;
00200    }
00201 
00202    if (muteme && frame->datalen > 0) {
00203       ast_frame_clear(frame);
00204    }
00205 
00206    /* Write frame out to respective factory */
00207    ast_slinfactory_feed(factory, frame);
00208 
00209    /* If we need to notify the respective handler of this audiohook, do so */
00210    if ((ast_test_flag(audiohook, AST_AUDIOHOOK_TRIGGER_MODE) == AST_AUDIOHOOK_TRIGGER_READ) && (direction == AST_AUDIOHOOK_DIRECTION_READ)) {
00211       ast_cond_signal(&audiohook->trigger);
00212    } else if ((ast_test_flag(audiohook, AST_AUDIOHOOK_TRIGGER_MODE) == AST_AUDIOHOOK_TRIGGER_WRITE) && (direction == AST_AUDIOHOOK_DIRECTION_WRITE)) {
00213       ast_cond_signal(&audiohook->trigger);
00214    } else if (ast_test_flag(audiohook, AST_AUDIOHOOK_TRIGGER_SYNC)) {
00215       ast_cond_signal(&audiohook->trigger);
00216    }
00217 
00218    return 0;
00219 }

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 
) [read]

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

Parameters:
chan Channel that the list is coming off of
audiohook_list List of audiohooks
direction Direction frame is coming in from
frame The frame itself
Returns:
Return frame on success, NULL on failure

Definition at line 983 of file audiohook.c.

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

00984 {
00985    /* Pass off frame to it's respective list write function */
00986    if (frame->frametype == AST_FRAME_VOICE) {
00987       return audio_audiohook_write_list(chan, audiohook_list, direction, frame);
00988    } else if (frame->frametype == AST_FRAME_DTMF) {
00989       return dtmf_audiohook_write_list(chan, audiohook_list, direction, frame);
00990    } else {
00991       return frame;
00992    }
00993 }

int ast_audiohook_write_list_empty ( struct ast_audiohook_list audiohook_list  ) 

Determine if a audiohook_list is empty or not.

Parameters:
audiohook Audiohook to check. (NULL also means empty)
retval 0 false, 1 true

Definition at line 968 of file audiohook.c.

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

00969 {
00970    return !audiohook_list
00971       || (AST_LIST_EMPTY(&audiohook_list->spy_list)
00972          && AST_LIST_EMPTY(&audiohook_list->whisper_list)
00973          && AST_LIST_EMPTY(&audiohook_list->manipulate_list));
00974 }

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:
chan The channel on which to find the spies
source The audiohook's source
type The type of audiohook
Returns:
Return the number of audiohooks which are from the source specified
Note: Function performs nlocking.

Definition at line 1013 of file audiohook.c.

References AST_AUDIOHOOK_TYPE_MANIPULATE, AST_AUDIOHOOK_TYPE_SPY, AST_AUDIOHOOK_TYPE_WHISPER, ast_channel_audiohooks(), ast_debug, 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 feature_automixmonitor().

01014 {
01015    int count = 0;
01016    struct ast_audiohook *ah = NULL;
01017 
01018    if (!ast_channel_audiohooks(chan)) {
01019       return -1;
01020    }
01021 
01022    switch (type) {
01023       case AST_AUDIOHOOK_TYPE_SPY:
01024          AST_LIST_TRAVERSE(&ast_channel_audiohooks(chan)->spy_list, ah, list) {
01025             if (!strcmp(ah->source, source)) {
01026                count++;
01027             }
01028          }
01029          break;
01030       case AST_AUDIOHOOK_TYPE_WHISPER:
01031          AST_LIST_TRAVERSE(&ast_channel_audiohooks(chan)->whisper_list, ah, list) {
01032             if (!strcmp(ah->source, source)) {
01033                count++;
01034             }
01035          }
01036          break;
01037       case AST_AUDIOHOOK_TYPE_MANIPULATE:
01038          AST_LIST_TRAVERSE(&ast_channel_audiohooks(chan)->manipulate_list, ah, list) {
01039             if (!strcmp(ah->source, source)) {
01040                count++;
01041             }
01042          }
01043          break;
01044       default:
01045          ast_debug(1, "Invalid audiohook type supplied, (%u)\n", type);
01046          return -1;
01047    }
01048 
01049    return count;
01050 }

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:
chan The channel on which to find the spies
source The source of the audiohook
type The type of spy to look for
Returns:
Return the number of running audiohooks which are from the source specified
Note: Function performs no locking.

Definition at line 1053 of file audiohook.c.

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, ast_audiohook_list::manipulate_list, NULL, ast_audiohook::source, ast_audiohook_list::spy_list, ast_audiohook::status, and ast_audiohook_list::whisper_list.

01054 {
01055    int count = 0;
01056    struct ast_audiohook *ah = NULL;
01057    if (!ast_channel_audiohooks(chan))
01058       return -1;
01059 
01060    switch (type) {
01061       case AST_AUDIOHOOK_TYPE_SPY:
01062          AST_LIST_TRAVERSE(&ast_channel_audiohooks(chan)->spy_list, ah, list) {
01063             if ((!strcmp(ah->source, source)) && (ah->status == AST_AUDIOHOOK_STATUS_RUNNING))
01064                count++;
01065          }
01066          break;
01067       case AST_AUDIOHOOK_TYPE_WHISPER:
01068          AST_LIST_TRAVERSE(&ast_channel_audiohooks(chan)->whisper_list, ah, list) {
01069             if ((!strcmp(ah->source, source)) && (ah->status == AST_AUDIOHOOK_STATUS_RUNNING))
01070                count++;
01071          }
01072          break;
01073       case AST_AUDIOHOOK_TYPE_MANIPULATE:
01074          AST_LIST_TRAVERSE(&ast_channel_audiohooks(chan)->manipulate_list, ah, list) {
01075             if ((!strcmp(ah->source, source)) && (ah->status == AST_AUDIOHOOK_STATUS_RUNNING))
01076                count++;
01077          }
01078          break;
01079       default:
01080          ast_debug(1, "Invalid audiohook type supplied, (%u)\n", type);
01081          return -1;
01082    }
01083    return count;
01084 }

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, read]

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:
chan Channel that the list is coming off of
audiohook_list List of audiohooks
direction Direction frame is coming in from
frame The frame itself
Returns:
Return frame on success, NULL on failure

Definition at line 847 of file audiohook.c.

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

Referenced by ast_audiohook_write_list().

00848 {
00849    struct ast_frame *start_frame = frame, *middle_frame = frame, *end_frame = frame;
00850    struct ast_audiohook *audiohook = NULL;
00851    int samples;
00852    int middle_frame_manipulated = 0;
00853    int removed = 0;
00854 
00855    /* ---Part_1. translate start_frame to SLINEAR if necessary. */
00856    if (!(middle_frame = audiohook_list_translate_to_slin(audiohook_list, direction, start_frame))) {
00857       return frame;
00858    }
00859    samples = middle_frame->samples;
00860 
00861    /* ---Part_2: Send middle_frame to spy and manipulator lists.  middle_frame is guaranteed to be SLINEAR here.*/
00862    /* Queue up signed linear frame to each spy */
00863    AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->spy_list, audiohook, list) {
00864       ast_audiohook_lock(audiohook);
00865       if (audiohook->status != AST_AUDIOHOOK_STATUS_RUNNING) {
00866          AST_LIST_REMOVE_CURRENT(list);
00867          removed = 1;
00868          ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_DONE);
00869          ast_audiohook_unlock(audiohook);
00870          if (ast_channel_is_bridged(chan)) {
00871             ast_channel_set_unbridged_nolock(chan, 1);
00872          }
00873          continue;
00874       }
00875       audiohook_set_internal_rate(audiohook, audiohook_list->list_internal_samp_rate, 1);
00876       ast_audiohook_write_frame(audiohook, direction, middle_frame);
00877       ast_audiohook_unlock(audiohook);
00878    }
00879    AST_LIST_TRAVERSE_SAFE_END;
00880 
00881    /* If this frame is being written out to the channel then we need to use whisper sources */
00882    if (!AST_LIST_EMPTY(&audiohook_list->whisper_list)) {
00883       int i = 0;
00884       short read_buf[samples], combine_buf[samples], *data1 = NULL, *data2 = NULL;
00885       memset(&combine_buf, 0, sizeof(combine_buf));
00886       AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->whisper_list, audiohook, list) {
00887          struct ast_slinfactory *factory = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook->read_factory : &audiohook->write_factory);
00888          ast_audiohook_lock(audiohook);
00889          if (audiohook->status != AST_AUDIOHOOK_STATUS_RUNNING) {
00890             AST_LIST_REMOVE_CURRENT(list);
00891             removed = 1;
00892             ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_DONE);
00893             ast_audiohook_unlock(audiohook);
00894             if (ast_channel_is_bridged(chan)) {
00895                ast_channel_set_unbridged_nolock(chan, 1);
00896             }
00897             continue;
00898          }
00899          audiohook_set_internal_rate(audiohook, audiohook_list->list_internal_samp_rate, 1);
00900          if (ast_slinfactory_available(factory) >= samples && ast_slinfactory_read(factory, read_buf, samples)) {
00901             /* Take audio from this whisper source and combine it into our main buffer */
00902             for (i = 0, data1 = combine_buf, data2 = read_buf; i < samples; i++, data1++, data2++) {
00903                ast_slinear_saturated_add(data1, data2);
00904             }
00905          }
00906          ast_audiohook_unlock(audiohook);
00907       }
00908       AST_LIST_TRAVERSE_SAFE_END;
00909       /* We take all of the combined whisper sources and combine them into the audio being written out */
00910       for (i = 0, data1 = middle_frame->data.ptr, data2 = combine_buf; i < samples; i++, data1++, data2++) {
00911          ast_slinear_saturated_add(data1, data2);
00912       }
00913       middle_frame_manipulated = 1;
00914    }
00915 
00916    /* Pass off frame to manipulate audiohooks */
00917    if (!AST_LIST_EMPTY(&audiohook_list->manipulate_list)) {
00918       AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->manipulate_list, audiohook, list) {
00919          ast_audiohook_lock(audiohook);
00920          if (audiohook->status != AST_AUDIOHOOK_STATUS_RUNNING) {
00921             AST_LIST_REMOVE_CURRENT(list);
00922             removed = 1;
00923             ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_DONE);
00924             ast_audiohook_unlock(audiohook);
00925             /* We basically drop all of our links to the manipulate audiohook and prod it to do it's own destructive things */
00926             audiohook->manipulate_callback(audiohook, chan, NULL, direction);
00927             if (ast_channel_is_bridged(chan)) {
00928                ast_channel_set_unbridged_nolock(chan, 1);
00929             }
00930             continue;
00931          }
00932          audiohook_set_internal_rate(audiohook, audiohook_list->list_internal_samp_rate, 1);
00933          /* Feed in frame to manipulation. */
00934          if (!audiohook->manipulate_callback(audiohook, chan, middle_frame, direction)) {
00935             /* If the manipulation fails then the frame will be returned in its original state.
00936              * Since there are potentially more manipulator callbacks in the list, no action should
00937              * be taken here to exit early. */
00938              middle_frame_manipulated = 1;
00939          }
00940          ast_audiohook_unlock(audiohook);
00941       }
00942       AST_LIST_TRAVERSE_SAFE_END;
00943    }
00944 
00945    /* ---Part_3: Decide what to do with the end_frame (whether to transcode or not) */
00946    if (middle_frame_manipulated) {
00947       if (!(end_frame = audiohook_list_translate_to_native(audiohook_list, direction, middle_frame, start_frame->subclass.format))) {
00948          /* translation failed, so just pass back the input frame */
00949          end_frame = start_frame;
00950       }
00951    } else {
00952       end_frame = start_frame;
00953    }
00954    /* clean up our middle_frame if required */
00955    if (middle_frame != end_frame) {
00956       ast_frfree(middle_frame);
00957       middle_frame = NULL;
00958    }
00959 
00960    /* Before returning, if an audiohook got removed, reset samplerate compatibility */
00961    if (removed) {
00962       audiohook_list_set_samplerate_compatibility(audiohook_list);
00963    }
00964 
00965    return end_frame;
00966 }

static void audiohook_list_set_samplerate_compatibility ( struct ast_audiohook_list audiohook_list  )  [static]

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, read]

Definition at line 800 of file audiohook.c.

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_audiohook_translate::format, ast_frame_subclass::format, NULL, ast_audiohook_list::out_translate, ast_frame::subclass, and ast_audiohook_translate::trans_pvt.

Referenced by audio_audiohook_write_list().

00802 {
00803    struct ast_audiohook_translate *out_translate = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook_list->out_translate[0] : &audiohook_list->out_translate[1]);
00804    struct ast_frame *outframe = NULL;
00805    if (ast_format_cmp(slin_frame->subclass.format, outformat) == AST_FORMAT_CMP_NOT_EQUAL) {
00806       /* rebuild translators if necessary */
00807       if (ast_format_cmp(out_translate->format, outformat) == AST_FORMAT_CMP_NOT_EQUAL) {
00808          if (out_translate->trans_pvt) {
00809             ast_translator_free_path(out_translate->trans_pvt);
00810          }
00811          if (!(out_translate->trans_pvt = ast_translator_build_path(outformat, slin_frame->subclass.format))) {
00812             return NULL;
00813          }
00814          ao2_replace(out_translate->format, outformat);
00815       }
00816       /* translate back to the format the frame came in as. */
00817       if (!(outframe = ast_translate(out_translate->trans_pvt, slin_frame, 0))) {
00818          return NULL;
00819       }
00820    }
00821    return outframe;
00822 }

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, read]

Definition at line 761 of file audiohook.c.

References ao2_replace, AST_AUDIOHOOK_DIRECTION_READ, 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_translate(), ast_translator_build_path(), ast_translator_free_path(), ast_audiohook_translate::format, ast_frame_subclass::format, ast_audiohook_list::in_translate, ast_audiohook_list::list_internal_samp_rate, MAX, ast_audiohook_list::native_slin_compatible, NULL, ast_frame::subclass, and ast_audiohook_translate::trans_pvt.

Referenced by audio_audiohook_write_list().

00763 {
00764    struct ast_audiohook_translate *in_translate = (direction == AST_AUDIOHOOK_DIRECTION_READ ?
00765       &audiohook_list->in_translate[0] : &audiohook_list->in_translate[1]);
00766    struct ast_frame *new_frame = frame;
00767    struct ast_format *slin;
00768 
00769    /* If we are capable of maintaining doing samplerates other that 8khz, update
00770     * the internal audiohook_list's rate and higher samplerate audio arrives. By
00771     * updating the list's rate, all the audiohooks in the list will be updated as well
00772     * as the are written and read from. */
00773    if (audiohook_list->native_slin_compatible) {
00774       audiohook_list->list_internal_samp_rate =
00775          MAX(ast_format_get_sample_rate(frame->subclass.format), audiohook_list->list_internal_samp_rate);
00776    }
00777 
00778    slin = ast_format_cache_get_slin_by_rate(audiohook_list->list_internal_samp_rate);
00779    if (ast_format_cmp(frame->subclass.format, slin) == AST_FORMAT_CMP_EQUAL) {
00780       return new_frame;
00781    }
00782 
00783    if (ast_format_cmp(frame->subclass.format, in_translate->format) == AST_FORMAT_CMP_NOT_EQUAL) {
00784       if (in_translate->trans_pvt) {
00785          ast_translator_free_path(in_translate->trans_pvt);
00786       }
00787       if (!(in_translate->trans_pvt = ast_translator_build_path(slin, frame->subclass.format))) {
00788          return NULL;
00789       }
00790       ao2_replace(in_translate->format, frame->subclass.format);
00791    }
00792 
00793    if (!(new_frame = ast_translate(in_translate->trans_pvt, frame, 0))) {
00794       return NULL;
00795    }
00796 
00797    return new_frame;
00798 }

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

Definition at line 594 of file audiohook.c.

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

Referenced by ast_audiohook_move_all(), and ast_audiohook_move_by_source().

00595 {
00596    enum ast_audiohook_status oldstatus;
00597 
00598    /* By locking both channels and the audiohook, we can assure that
00599     * another thread will not have a chance to read the audiohook's status
00600     * as done, even though ast_audiohook_remove signals the trigger
00601     * condition.
00602     */
00603    ast_audiohook_lock(audiohook);
00604    oldstatus = audiohook->status;
00605 
00606    ast_audiohook_remove(old_chan, audiohook);
00607    ast_audiohook_attach(new_chan, audiohook);
00608 
00609    audiohook->status = oldstatus;
00610    ast_audiohook_unlock(audiohook);
00611 }

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, read]

Definition at line 252 of file audiohook.c.

References abs, 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_tvdiff_ms(), ast_tvnow(), buf1, buf2, ast_frame::data, ast_frame_subclass::format, ast_frame::frametype, ast_audiohook::hook_internal_samp_rate, NULL, ast_audiohook::options, ast_frame::ptr, ast_audiohook::read_factory, ast_audiohook::read_time, ast_audiohook_options::read_volume, ast_frame::subclass, write_buf(), ast_audiohook::write_factory, ast_audiohook::write_time, and ast_audiohook_options::write_volume.

Referenced by audiohook_read_frame_helper().

00253 {
00254    int i = 0, usable_read, usable_write;
00255    short buf1[samples], buf2[samples], *read_buf = NULL, *write_buf = NULL, *final_buf = NULL, *data1 = NULL, *data2 = NULL;
00256    struct ast_frame frame = {
00257       .frametype = AST_FRAME_VOICE,
00258       .data.ptr = NULL,
00259       .datalen = sizeof(buf1),
00260       .samples = samples,
00261    };
00262 
00263    /* Make sure both factories have the required samples */
00264    usable_read = (ast_slinfactory_available(&audiohook->read_factory) >= samples ? 1 : 0);
00265    usable_write = (ast_slinfactory_available(&audiohook->write_factory) >= samples ? 1 : 0);
00266 
00267    if (!usable_read && !usable_write) {
00268       /* If both factories are unusable bail out */
00269       ast_debug(1, "Read factory %p and write factory %p both fail to provide %zu samples\n", &audiohook->read_factory, &audiohook->write_factory, samples);
00270       return NULL;
00271    }
00272 
00273    /* If we want to provide only a read factory make sure we aren't waiting for other audio */
00274    if (usable_read && !usable_write && (ast_tvdiff_ms(ast_tvnow(), audiohook->write_time) < (samples/8)*2)) {
00275       ast_debug(3, "Write factory %p was pretty quick last time, waiting for them.\n", &audiohook->write_factory);
00276       return NULL;
00277    }
00278 
00279    /* If we want to provide only a write factory make sure we aren't waiting for other audio */
00280    if (usable_write && !usable_read && (ast_tvdiff_ms(ast_tvnow(), audiohook->read_time) < (samples/8)*2)) {
00281       ast_debug(3, "Read factory %p was pretty quick last time, waiting for them.\n", &audiohook->read_factory);
00282       return NULL;
00283    }
00284 
00285    /* Start with the read factory... if there are enough samples, read them in */
00286    if (usable_read) {
00287       if (ast_slinfactory_read(&audiohook->read_factory, buf1, samples)) {
00288          read_buf = buf1;
00289          /* Adjust read volume if need be */
00290          if (audiohook->options.read_volume) {
00291             int count = 0;
00292             short adjust_value = abs(audiohook->options.read_volume);
00293             for (count = 0; count < samples; count++) {
00294                if (audiohook->options.read_volume > 0) {
00295                   ast_slinear_saturated_multiply(&buf1[count], &adjust_value);
00296                } else if (audiohook->options.read_volume < 0) {
00297                   ast_slinear_saturated_divide(&buf1[count], &adjust_value);
00298                }
00299             }
00300          }
00301       }
00302    } else {
00303       ast_debug(1, "Failed to get %d samples from read factory %p\n", (int)samples, &audiohook->read_factory);
00304    }
00305 
00306    /* Move on to the write factory... if there are enough samples, read them in */
00307    if (usable_write) {
00308       if (ast_slinfactory_read(&audiohook->write_factory, buf2, samples)) {
00309          write_buf = buf2;
00310          /* Adjust write volume if need be */
00311          if (audiohook->options.write_volume) {
00312             int count = 0;
00313             short adjust_value = abs(audiohook->options.write_volume);
00314             for (count = 0; count < samples; count++) {
00315                if (audiohook->options.write_volume > 0) {
00316                   ast_slinear_saturated_multiply(&buf2[count], &adjust_value);
00317                } else if (audiohook->options.write_volume < 0) {
00318                   ast_slinear_saturated_divide(&buf2[count], &adjust_value);
00319                }
00320             }
00321          }
00322       }
00323    } else {
00324       ast_debug(1, "Failed to get %d samples from write factory %p\n", (int)samples, &audiohook->write_factory);
00325    }
00326 
00327    /* Basically we figure out which buffer to use... and if mixing can be done here */
00328    if (read_buf && read_reference) {
00329       frame.data.ptr = buf1;
00330       *read_reference = ast_frdup(&frame);
00331    }
00332    if (write_buf && write_reference) {
00333       frame.data.ptr = buf2;
00334       *write_reference = ast_frdup(&frame);
00335    }
00336 
00337    if (read_buf && write_buf) {
00338       for (i = 0, data1 = read_buf, data2 = write_buf; i < samples; i++, data1++, data2++) {
00339          ast_slinear_saturated_add(data1, data2);
00340       }
00341       final_buf = buf1;
00342    } else if (read_buf) {
00343       final_buf = buf1;
00344    } else if (write_buf) {
00345       final_buf = buf2;
00346    } else {
00347       return NULL;
00348    }
00349 
00350    /* Make the final buffer part of the frame, so it gets duplicated fine */
00351    frame.data.ptr = final_buf;
00352 
00353    frame.subclass.format = ast_format_cache_get_slin_by_rate(audiohook->hook_internal_samp_rate);
00354 
00355    /* Yahoo, a combined copy of the audio! */
00356    return ast_frdup(&frame);
00357 }

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, read]

Definition at line 359 of file audiohook.c.

References ao2_replace, 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_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().

00360 {
00361    struct ast_frame *read_frame = NULL, *final_frame = NULL;
00362    struct ast_format *slin;
00363 
00364    audiohook_set_internal_rate(audiohook, ast_format_get_sample_rate(format), 1);
00365 
00366    if (!(read_frame = (direction == AST_AUDIOHOOK_DIRECTION_BOTH ?
00367       audiohook_read_frame_both(audiohook, samples, read_reference, write_reference) :
00368       audiohook_read_frame_single(audiohook, samples, direction)))) {
00369       return NULL;
00370    }
00371 
00372    slin = ast_format_cache_get_slin_by_rate(audiohook->hook_internal_samp_rate);
00373 
00374    /* If they don't want signed linear back out, we'll have to send it through the translation path */
00375    if (ast_format_cmp(format, slin) != AST_FORMAT_CMP_EQUAL) {
00376       /* Rebuild translation path if different format then previously */
00377       if (ast_format_cmp(format, audiohook->format) == AST_FORMAT_CMP_NOT_EQUAL) {
00378          if (audiohook->trans_pvt) {
00379             ast_translator_free_path(audiohook->trans_pvt);
00380             audiohook->trans_pvt = NULL;
00381          }
00382 
00383          /* 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 */
00384          if (!(audiohook->trans_pvt = ast_translator_build_path(format, slin))) {
00385             ast_frfree(read_frame);
00386             return NULL;
00387          }
00388          ao2_replace(audiohook->format, format);
00389       }
00390       /* Convert to requested format, and allow the read in frame to be freed */
00391       final_frame = ast_translate(audiohook->trans_pvt, read_frame, 1);
00392    } else {
00393       final_frame = read_frame;
00394    }
00395 
00396    return final_frame;
00397 }

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

Definition at line 221 of file audiohook.c.

References AST_AUDIOHOOK_DIRECTION_READ, ast_format_cache_get_slin_by_rate(), ast_frame_adjust_volume(), 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_audiohook::write_factory, and ast_audiohook_options::write_volume.

Referenced by audiohook_read_frame_helper().

00222 {
00223    struct ast_slinfactory *factory = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook->read_factory : &audiohook->write_factory);
00224    int vol = (direction == AST_AUDIOHOOK_DIRECTION_READ ? audiohook->options.read_volume : audiohook->options.write_volume);
00225    short buf[samples];
00226    struct ast_frame frame = {
00227       .frametype = AST_FRAME_VOICE,
00228       .subclass.format = ast_format_cache_get_slin_by_rate(audiohook->hook_internal_samp_rate),
00229       .data.ptr = buf,
00230       .datalen = sizeof(buf),
00231       .samples = samples,
00232    };
00233 
00234    /* Ensure the factory is able to give us the samples we want */
00235    if (samples > ast_slinfactory_available(factory)) {
00236       return NULL;
00237    }
00238 
00239    /* Read data in from factory */
00240    if (!ast_slinfactory_read(factory, buf, samples)) {
00241       return NULL;
00242    }
00243 
00244    /* If a volume adjustment needs to be applied apply it */
00245    if (vol) {
00246       ast_frame_adjust_volume(&frame, vol);
00247    }
00248 
00249    return ast_frdup(&frame);
00250 }

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

Definition at line 69 of file audiohook.c.

References AST_AUDIOHOOK_TYPE_SPY, AST_AUDIOHOOK_TYPE_WHISPER, ast_format_cache_get_slin_by_rate(), ast_slinfactory_destroy(), and ast_slinfactory_init_with_format().

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

00070 {
00071    struct ast_format *slin;
00072 
00073    if (audiohook->hook_internal_samp_rate == rate) {
00074       return 0;
00075    }
00076 
00077    audiohook->hook_internal_samp_rate = rate;
00078 
00079    slin = ast_format_cache_get_slin_by_rate(rate);
00080 
00081    /* Setup the factories that are needed for this audiohook type */
00082    switch (audiohook->type) {
00083    case AST_AUDIOHOOK_TYPE_SPY:
00084    case AST_AUDIOHOOK_TYPE_WHISPER:
00085       if (reset) {
00086          ast_slinfactory_destroy(&audiohook->read_factory);
00087          ast_slinfactory_destroy(&audiohook->write_factory);
00088       }
00089       ast_slinfactory_init_with_format(&audiohook->read_factory, slin);
00090       ast_slinfactory_init_with_format(&audiohook->write_factory, slin);
00091       break;
00092    default:
00093       break;
00094    }
00095 
00096    return 0;
00097 }

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:
audiohook Audiohook attached to the channel
chan Channel we are attached to
frame Frame of audio we want to manipulate
direction Direction the audio came in from
Returns:
Returns 0 on success, -1 on failure

Definition at line 1123 of file audiohook.c.

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

Referenced by audiohook_volume_get().

01124 {
01125    struct ast_datastore *datastore = NULL;
01126    struct audiohook_volume *audiohook_volume = NULL;
01127    int *gain = NULL;
01128 
01129    /* If the audiohook is shutting down don't even bother */
01130    if (audiohook->status == AST_AUDIOHOOK_STATUS_DONE) {
01131       return 0;
01132    }
01133 
01134    /* Try to find the datastore containg adjustment information, if we can't just bail out */
01135    if (!(datastore = ast_channel_datastore_find(chan, &audiohook_volume_datastore, NULL))) {
01136       return 0;
01137    }
01138 
01139    audiohook_volume = datastore->data;
01140 
01141    /* Based on direction grab the appropriate adjustment value */
01142    if (direction == AST_AUDIOHOOK_DIRECTION_READ) {
01143       gain = &audiohook_volume->read_adjustment;
01144    } else if (direction == AST_AUDIOHOOK_DIRECTION_WRITE) {
01145       gain = &audiohook_volume->write_adjustment;
01146    }
01147 
01148    /* If an adjustment value is present modify the frame */
01149    if (gain && *gain) {
01150       ast_frame_adjust_volume(frame, *gain);
01151    }
01152 
01153    return 0;
01154 }

static void audiohook_volume_destroy ( void *  data  )  [static]

Callback used to destroy the audiohook volume datastore.

Parameters:
data Volume information structure
Returns:
Returns nothing

Definition at line 1097 of file audiohook.c.

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

01098 {
01099    struct audiohook_volume *audiohook_volume = data;
01100 
01101    /* Destroy the audiohook as it is no longer in use */
01102    ast_audiohook_destroy(&audiohook_volume->audiohook);
01103 
01104    /* Finally free ourselves, we are of no more use */
01105    ast_free(audiohook_volume);
01106 
01107    return;
01108 }

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

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

Parameters:
chan Channel to look on
create Whether to create the datastore if not found
Returns:
Returns audiohook_volume structure on success, NULL on failure

Definition at line 1161 of file audiohook.c.

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(), ast_datastore::data, ast_audiohook::manipulate_callback, and NULL.

Referenced by ast_audiohook_volume_adjust(), ast_audiohook_volume_get(), and ast_audiohook_volume_set().

01162 {
01163    struct ast_datastore *datastore = NULL;
01164    struct audiohook_volume *audiohook_volume = NULL;
01165 
01166    /* If we are able to find the datastore return the contents (which is actually an audiohook_volume structure) */
01167    if ((datastore = ast_channel_datastore_find(chan, &audiohook_volume_datastore, NULL))) {
01168       return datastore->data;
01169    }
01170 
01171    /* 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 */
01172    if (!create || !(datastore = ast_datastore_alloc(&audiohook_volume_datastore, NULL))) {
01173       return NULL;
01174    }
01175 
01176    /* Create a new audiohook_volume structure to contain our adjustments and audiohook */
01177    if (!(audiohook_volume = ast_calloc(1, sizeof(*audiohook_volume)))) {
01178       ast_datastore_free(datastore);
01179       return NULL;
01180    }
01181 
01182    /* Setup our audiohook structure so we can manipulate the audio */
01183    ast_audiohook_init(&audiohook_volume->audiohook, AST_AUDIOHOOK_TYPE_MANIPULATE, "Volume", AST_AUDIOHOOK_MANIPULATE_ALL_RATES);
01184    audiohook_volume->audiohook.manipulate_callback = audiohook_volume_callback;
01185 
01186    /* Attach the audiohook_volume blob to the datastore and attach to the channel */
01187    datastore->data = audiohook_volume;
01188    ast_channel_datastore_add(chan, datastore);
01189 
01190    /* All is well... put the audiohook into motion */
01191    ast_audiohook_attach(chan, &audiohook_volume->audiohook);
01192 
01193    return audiohook_volume;
01194 }

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, read]

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

Parameters:
chan Channel that the list is coming off of
audiohook_list List of audiohooks
direction Direction frame is coming in from
frame The frame itself
Returns:
Return frame on success, NULL on failure

Definition at line 729 of file audiohook.c.

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

00730 {
00731    struct ast_audiohook *audiohook = NULL;
00732    int removed = 0;
00733 
00734    AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->manipulate_list, audiohook, list) {
00735       ast_audiohook_lock(audiohook);
00736       if (audiohook->status != AST_AUDIOHOOK_STATUS_RUNNING) {
00737          AST_LIST_REMOVE_CURRENT(list);
00738          removed = 1;
00739          ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_DONE);
00740          ast_audiohook_unlock(audiohook);
00741          audiohook->manipulate_callback(audiohook, NULL, NULL, 0);
00742          if (ast_channel_is_bridged(chan)) {
00743             ast_channel_set_unbridged_nolock(chan, 1);
00744          }
00745          continue;
00746       }
00747       if (ast_test_flag(audiohook, AST_AUDIOHOOK_WANTS_DTMF)) {
00748          audiohook->manipulate_callback(audiohook, chan, frame, direction);
00749       }
00750       ast_audiohook_unlock(audiohook);
00751    }
00752    AST_LIST_TRAVERSE_SAFE_END;
00753 
00754    /* if an audiohook got removed, reset samplerate compatibility */
00755    if (removed) {
00756       audiohook_list_set_samplerate_compatibility(audiohook_list);
00757    }
00758    return frame;
00759 }

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

find an audiohook based on its source

Parameters:
audiohook_list The list of audiohooks to search in
source The source of the audiohook we wish to find
Returns:
Return the corresponding audiohook or NULL if it cannot be found.

Definition at line 569 of file audiohook.c.

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

00570 {
00571    struct ast_audiohook *audiohook = NULL;
00572 
00573    AST_LIST_TRAVERSE(&audiohook_list->spy_list, audiohook, list) {
00574       if (!strcasecmp(audiohook->source, source)) {
00575          return audiohook;
00576       }
00577    }
00578 
00579    AST_LIST_TRAVERSE(&audiohook_list->whisper_list, audiohook, list) {
00580       if (!strcasecmp(audiohook->source, source)) {
00581          return audiohook;
00582       }
00583    }
00584 
00585    AST_LIST_TRAVERSE(&audiohook_list->manipulate_list, audiohook, list) {
00586       if (!strcasecmp(audiohook->source, source)) {
00587          return audiohook;
00588       }
00589    }
00590 
00591    return NULL;
00592 }


Variable Documentation

Initial value:

 {
   .type = "Volume",
   .destroy = audiohook_volume_destroy,
}
Datastore used to store audiohook volume information.

Definition at line 1111 of file audiohook.c.


Generated on Thu Apr 16 06:29:02 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6