Mon Mar 19 11:30:36 2012

Asterisk developer's documentation


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"

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

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.
int 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)
 Initialize an audiohook structure.
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.
ast_frameast_audiohook_read_frame (struct ast_audiohook *audiohook, size_t samples, enum ast_audiohook_direction direction, format_t format)
 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.
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)
 determines 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 struct ast_frameaudiohook_read_frame_both (struct ast_audiohook *audiohook, size_t samples)
static struct ast_frameaudiohook_read_frame_single (struct ast_audiohook *audiohook, size_t samples, enum ast_audiohook_direction direction)
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.


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 342 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_lock, ast_channel_unlock, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_TAIL, ast_channel::audiohooks, ast_audiohook_list::manipulate_list, ast_audiohook_list::spy_list, ast_audiohook::type, and ast_audiohook_list::whisper_list.

Referenced by ast_audiohook_move_by_source(), audiohook_volume_get(), enable_jack_hook(), mute_add_audiohook(), pitchshift_helper(), speex_write(), start_spying(), startmon(), and volume_write().

00343 {
00344    ast_channel_lock(chan);
00345 
00346    if (!chan->audiohooks) {
00347       /* Whoops... allocate a new structure */
00348       if (!(chan->audiohooks = ast_calloc(1, sizeof(*chan->audiohooks)))) {
00349          ast_channel_unlock(chan);
00350          return -1;
00351       }
00352       AST_LIST_HEAD_INIT_NOLOCK(&chan->audiohooks->spy_list);
00353       AST_LIST_HEAD_INIT_NOLOCK(&chan->audiohooks->whisper_list);
00354       AST_LIST_HEAD_INIT_NOLOCK(&chan->audiohooks->manipulate_list);
00355    }
00356 
00357    /* Drop into respective list */
00358    if (audiohook->type == AST_AUDIOHOOK_TYPE_SPY)
00359       AST_LIST_INSERT_TAIL(&chan->audiohooks->spy_list, audiohook, list);
00360    else if (audiohook->type == AST_AUDIOHOOK_TYPE_WHISPER)
00361       AST_LIST_INSERT_TAIL(&chan->audiohooks->whisper_list, audiohook, list);
00362    else if (audiohook->type == AST_AUDIOHOOK_TYPE_MANIPULATE)
00363       AST_LIST_INSERT_TAIL(&chan->audiohooks->manipulate_list, audiohook, list);
00364 
00365    /* Change status over to running since it is now attached */
00366    ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_RUNNING);
00367 
00368    ast_channel_unlock(chan);
00369 
00370    return 0;
00371 }

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

References AST_AUDIOHOOK_TYPE_SPY, AST_AUDIOHOOK_TYPE_WHISPER, ast_cond_destroy, ast_mutex_destroy, ast_slinfactory_destroy(), ast_translator_free_path(), 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(), destroy_callback(), destroy_jack_data(), destroy_monitor_audiohook(), and launch_monitor_thread().

00092 {
00093    /* Drop the factories used by this audiohook type */
00094    switch (audiohook->type) {
00095    case AST_AUDIOHOOK_TYPE_SPY:
00096       ast_slinfactory_destroy(&audiohook->read_factory);
00097    case AST_AUDIOHOOK_TYPE_WHISPER:
00098       ast_slinfactory_destroy(&audiohook->write_factory);
00099       break;
00100    default:
00101       break;
00102    }
00103 
00104    /* Destroy translation path if present */
00105    if (audiohook->trans_pvt)
00106       ast_translator_free_path(audiohook->trans_pvt);
00107 
00108    /* Lock and trigger be gone! */
00109    ast_cond_destroy(&audiohook->trigger);
00110    ast_mutex_destroy(&audiohook->lock);
00111 
00112    return 0;
00113 }

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 395 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_monitor_audiohook(), disable_jack_hook(), and speex_write().

00396 {
00397    if (audiohook->status == AST_AUDIOHOOK_STATUS_NEW || audiohook->status == AST_AUDIOHOOK_STATUS_DONE)
00398       return 0;
00399 
00400    ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_SHUTDOWN);
00401 
00402    while (audiohook->status != AST_AUDIOHOOK_STATUS_DONE)
00403       ast_audiohook_trigger_wait(audiohook);
00404 
00405    return 0;
00406 }

int ast_audiohook_detach_list ( struct ast_audiohook_list audiohook_list  ) 

Detach audiohooks from list and destroy said list.

Parameters:
audiohook_list List of audiohooks
Returns:
Returns 0 on success, -1 on failure

Definition at line 412 of file audiohook.c.

References AST_AUDIOHOOK_STATUS_DONE, ast_audiohook_update_status(), ast_free, AST_LIST_REMOVE_HEAD, ast_translator_free_path(), ast_audiohook_list::in_translate, ast_audiohook::list, ast_audiohook_list::manipulate_list, 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_hangup(), and ast_write().

00413 {
00414    int i = 0;
00415    struct ast_audiohook *audiohook = NULL;
00416 
00417    /* Drop any spies */
00418    while ((audiohook = AST_LIST_REMOVE_HEAD(&audiohook_list->spy_list, list))) {
00419       ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_DONE);
00420    }
00421 
00422    /* Drop any whispering sources */
00423    while ((audiohook = AST_LIST_REMOVE_HEAD(&audiohook_list->whisper_list, list))) {
00424       ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_DONE);
00425    }
00426 
00427    /* Drop any manipulaters */
00428    while ((audiohook = AST_LIST_REMOVE_HEAD(&audiohook_list->manipulate_list, list))) {
00429       ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_DONE);
00430       audiohook->manipulate_callback(audiohook, NULL, NULL, 0);
00431    }
00432 
00433    /* Drop translation paths if present */
00434    for (i = 0; i < 2; i++) {
00435       if (audiohook_list->in_translate[i].trans_pvt)
00436          ast_translator_free_path(audiohook_list->in_translate[i].trans_pvt);
00437       if (audiohook_list->out_translate[i].trans_pvt)
00438          ast_translator_free_path(audiohook_list->out_translate[i].trans_pvt);
00439    }
00440    
00441    /* Free ourselves */
00442    ast_free(audiohook_list);
00443 
00444    return 0;
00445 }

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

References AST_AUDIOHOOK_STATUS_DONE, AST_AUDIOHOOK_STATUS_SHUTDOWN, ast_audiohook_update_status(), ast_channel_lock, ast_channel_unlock, ast_channel::audiohooks, find_audiohook_by_source(), and ast_audiohook::status.

Referenced by handle_cli_mixmonitor(), and stop_mixmonitor_exec().

00504 {
00505    struct ast_audiohook *audiohook = NULL;
00506 
00507    ast_channel_lock(chan);
00508 
00509    /* Ensure the channel has audiohooks on it */
00510    if (!chan->audiohooks) {
00511       ast_channel_unlock(chan);
00512       return -1;
00513    }
00514 
00515    audiohook = find_audiohook_by_source(chan->audiohooks, source);
00516 
00517    ast_channel_unlock(chan);
00518 
00519    if (audiohook && audiohook->status != AST_AUDIOHOOK_STATUS_DONE)
00520       ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_SHUTDOWN);
00521 
00522    return (audiohook ? 0 : -1);
00523 }

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

Initialize an audiohook structure.

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

Definition at line 60 of file audiohook.c.

References AST_AUDIOHOOK_STATUS_NEW, AST_AUDIOHOOK_TYPE_SPY, AST_AUDIOHOOK_TYPE_WHISPER, ast_audiohook_update_status(), ast_cond_init, ast_mutex_init, and ast_slinfactory_init().

Referenced by audiohook_volume_get(), channel_spy(), enable_jack_hook(), initialize_mutehook(), launch_monitor_thread(), pitchshift_helper(), speex_write(), and volume_write().

00061 {
00062    /* Need to keep the type and source */
00063    audiohook->type = type;
00064    audiohook->source = source;
00065 
00066    /* Initialize lock that protects our audiohook */
00067    ast_mutex_init(&audiohook->lock);
00068    ast_cond_init(&audiohook->trigger, NULL);
00069 
00070    /* Setup the factories that are needed for this audiohook type */
00071    switch (type) {
00072    case AST_AUDIOHOOK_TYPE_SPY:
00073       ast_slinfactory_init(&audiohook->read_factory);
00074    case AST_AUDIOHOOK_TYPE_WHISPER:
00075       ast_slinfactory_init(&audiohook->write_factory);
00076       break;
00077    default:
00078       break;
00079    }
00080 
00081    /* Since we are just starting out... this audiohook is new */
00082    ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_NEW);
00083 
00084    return 0;
00085 }

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

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

Referenced by audiohook_inheritance_fixup().

00475 {
00476    struct ast_audiohook *audiohook;
00477    enum ast_audiohook_status oldstatus;
00478 
00479    if (!old_chan->audiohooks || !(audiohook = find_audiohook_by_source(old_chan->audiohooks, source))) {
00480       return;
00481    }
00482 
00483    /* By locking both channels and the audiohook, we can assure that
00484     * another thread will not have a chance to read the audiohook's status
00485     * as done, even though ast_audiohook_remove signals the trigger
00486     * condition.
00487     */
00488    ast_audiohook_lock(audiohook);
00489    oldstatus = audiohook->status;
00490 
00491    ast_audiohook_remove(old_chan, audiohook);
00492    ast_audiohook_attach(new_chan, audiohook);
00493 
00494    audiohook->status = oldstatus;
00495    ast_audiohook_unlock(audiohook);
00496 }

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

Reads a frame in from the audiohook structure.

Parameters:
audiohook Audiohook structure
samples Number of samples wanted
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 307 of file audiohook.c.

References AST_AUDIOHOOK_DIRECTION_BOTH, AST_FORMAT_SLINEAR, ast_frfree, ast_translate(), ast_translator_build_path(), ast_translator_free_path(), audiohook_read_frame_both(), audiohook_read_frame_single(), and read_frame().

Referenced by mixmonitor_thread(), and spy_generate().

00308 {
00309    struct ast_frame *read_frame = NULL, *final_frame = NULL;
00310 
00311    if (!(read_frame = (direction == AST_AUDIOHOOK_DIRECTION_BOTH ? audiohook_read_frame_both(audiohook, samples) : audiohook_read_frame_single(audiohook, samples, direction))))
00312       return NULL;
00313 
00314    /* If they don't want signed linear back out, we'll have to send it through the translation path */
00315    if (format != AST_FORMAT_SLINEAR) {
00316       /* Rebuild translation path if different format then previously */
00317       if (audiohook->format != format) {
00318          if (audiohook->trans_pvt) {
00319             ast_translator_free_path(audiohook->trans_pvt);
00320             audiohook->trans_pvt = NULL;
00321          }
00322          /* 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 */
00323          if (!(audiohook->trans_pvt = ast_translator_build_path(format, AST_FORMAT_SLINEAR))) {
00324             ast_frfree(read_frame);
00325             return NULL;
00326          }
00327       }
00328       /* Convert to requested format, and allow the read in frame to be freed */
00329       final_frame = ast_translate(audiohook->trans_pvt, read_frame, 1);
00330    } else {
00331       final_frame = read_frame;
00332    }
00333 
00334    return final_frame;
00335 }

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 535 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_lock, ast_channel_unlock, AST_LIST_REMOVE, ast_channel::audiohooks, ast_audiohook::list, ast_audiohook_list::manipulate_list, ast_audiohook_list::spy_list, ast_audiohook::type, and ast_audiohook_list::whisper_list.

Referenced by ast_audiohook_move_by_source(), and speex_write().

00536 {
00537    ast_channel_lock(chan);
00538 
00539    if (!chan->audiohooks) {
00540       ast_channel_unlock(chan);
00541       return -1;
00542    }
00543 
00544    if (audiohook->type == AST_AUDIOHOOK_TYPE_SPY)
00545       AST_LIST_REMOVE(&chan->audiohooks->spy_list, audiohook, list);
00546    else if (audiohook->type == AST_AUDIOHOOK_TYPE_WHISPER)
00547       AST_LIST_REMOVE(&chan->audiohooks->whisper_list, audiohook, list);
00548    else if (audiohook->type == AST_AUDIOHOOK_TYPE_MANIPULATE)
00549       AST_LIST_REMOVE(&chan->audiohooks->manipulate_list, audiohook, list);
00550 
00551    ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_DONE);
00552 
00553    ast_channel_unlock(chan);
00554 
00555    return 0;
00556 }

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

References ast_channel_lock, ast_channel_unlock, ast_clear_flag, ast_set_flag, ast_channel::audiohooks, and find_audiohook_by_source().

Referenced by manager_mute_mixmonitor().

01056 {
01057    struct ast_audiohook *audiohook = NULL;
01058 
01059    ast_channel_lock(chan);
01060 
01061    /* Ensure the channel has audiohooks on it */
01062    if (!chan->audiohooks) {
01063       ast_channel_unlock(chan);
01064       return -1;
01065    }
01066 
01067    audiohook = find_audiohook_by_source(chan->audiohooks, source);
01068 
01069    if (audiohook) {
01070       if (clear) {
01071          ast_clear_flag(audiohook, flag);
01072       } else {
01073          ast_set_flag(audiohook, flag);
01074       }
01075    }
01076 
01077    ast_channel_unlock(chan);
01078 
01079    return (audiohook ? 0 : -1);
01080 }

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

00775 {
00776    struct timeval wait;
00777    struct timespec ts;
00778 
00779    wait = ast_tvadd(ast_tvnow(), ast_samp2tv(50000, 1000));
00780    ts.tv_sec = wait.tv_sec;
00781    ts.tv_nsec = wait.tv_usec * 1000;
00782    
00783    ast_cond_timedwait(&audiohook->trigger, &audiohook->lock, &ts);
00784    
00785    return;
00786 }

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

00382 {
00383    ast_audiohook_lock(audiohook);
00384    if (audiohook->status != AST_AUDIOHOOK_STATUS_DONE) {
00385       audiohook->status = status;
00386       ast_cond_signal(&audiohook->trigger);
00387    }
00388    ast_audiohook_unlock(audiohook);
00389 }

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

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

Referenced by menu_callback().

01029 {
01030    struct audiohook_volume *audiohook_volume = NULL;
01031 
01032    /* Attempt to find the audiohook volume information, and create an audiohook if none exists */
01033    if (!(audiohook_volume = audiohook_volume_get(chan, 1))) {
01034       return -1;
01035    }
01036 
01037    /* Based on the direction change the specific adjustment value */
01038    if (direction == AST_AUDIOHOOK_DIRECTION_READ || direction == AST_AUDIOHOOK_DIRECTION_BOTH) {
01039       audiohook_volume->read_adjustment += volume;
01040    }
01041    if (direction == AST_AUDIOHOOK_DIRECTION_WRITE || direction == AST_AUDIOHOOK_DIRECTION_BOTH) {
01042       audiohook_volume->write_adjustment += volume;
01043    }
01044 
01045    return 0;
01046 }

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

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

Referenced by confbridge_exec().

01003 {
01004    struct audiohook_volume *audiohook_volume = NULL;
01005    int adjustment = 0;
01006 
01007    /* Attempt to find the audiohook volume information, but do not create it as we only want to look at the values */
01008    if (!(audiohook_volume = audiohook_volume_get(chan, 0))) {
01009       return 0;
01010    }
01011 
01012    /* Grab the adjustment value based on direction given */
01013    if (direction == AST_AUDIOHOOK_DIRECTION_READ) {
01014       adjustment = audiohook_volume->read_adjustment;
01015    } else if (direction == AST_AUDIOHOOK_DIRECTION_WRITE) {
01016       adjustment = audiohook_volume->write_adjustment;
01017    }
01018 
01019    return adjustment;
01020 }

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

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

Referenced by confbridge_exec().

00978 {
00979    struct audiohook_volume *audiohook_volume = NULL;
00980 
00981    /* Attempt to find the audiohook volume information, but only create it if we are not setting the adjustment value to zero */
00982    if (!(audiohook_volume = audiohook_volume_get(chan, (volume ? 1 : 0)))) {
00983       return -1;
00984    }
00985 
00986    /* Now based on the direction set the proper value */
00987    if (direction == AST_AUDIOHOOK_DIRECTION_READ || direction == AST_AUDIOHOOK_DIRECTION_BOTH) {
00988       audiohook_volume->read_adjustment = volume;
00989    }
00990    if (direction == AST_AUDIOHOOK_DIRECTION_WRITE || direction == AST_AUDIOHOOK_DIRECTION_BOTH) {
00991       audiohook_volume->write_adjustment = volume;
00992    }
00993 
00994    return 0;
00995 }

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 121 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_SYNC_TOLERANCE, AST_AUDIOHOOK_TRIGGER_MODE, AST_AUDIOHOOK_TRIGGER_READ, AST_AUDIOHOOK_TRIGGER_SYNC, AST_AUDIOHOOK_TRIGGER_WRITE, ast_cond_signal, ast_frame_clear(), ast_log(), ast_slinfactory_available(), ast_slinfactory_feed(), ast_slinfactory_flush(), ast_test_flag, ast_tvdiff_ms(), ast_tvnow(), ast_frame::datalen, LOG_DEBUG, option_debug, 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(), and channel_spy().

00122 {
00123    struct ast_slinfactory *factory = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook->read_factory : &audiohook->write_factory);
00124    struct ast_slinfactory *other_factory = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook->write_factory : &audiohook->read_factory);
00125    struct timeval *rwtime = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook->read_time : &audiohook->write_time), previous_time = *rwtime;
00126    int our_factory_samples;
00127    int our_factory_ms;
00128    int other_factory_samples;
00129    int other_factory_ms;
00130    int muteme = 0;
00131 
00132    /* Update last feeding time to be current */
00133    *rwtime = ast_tvnow();
00134 
00135    our_factory_samples = ast_slinfactory_available(factory);
00136    our_factory_ms = ast_tvdiff_ms(*rwtime, previous_time) + (our_factory_samples / 8);
00137    other_factory_samples = ast_slinfactory_available(other_factory);
00138    other_factory_ms = other_factory_samples / 8;
00139 
00140    if (ast_test_flag(audiohook, AST_AUDIOHOOK_TRIGGER_SYNC) && other_factory_samples && (our_factory_ms - other_factory_ms > AST_AUDIOHOOK_SYNC_TOLERANCE)) {
00141       if (option_debug)
00142          ast_log(LOG_DEBUG, "Flushing audiohook %p so it remains in sync\n", audiohook);
00143       ast_slinfactory_flush(factory);
00144       ast_slinfactory_flush(other_factory);
00145    }
00146 
00147    if (ast_test_flag(audiohook, AST_AUDIOHOOK_SMALL_QUEUE) && (our_factory_samples > 640 || other_factory_samples > 640)) {
00148       if (option_debug) {
00149          ast_log(LOG_DEBUG, "Audiohook %p has stale audio in its factories. Flushing them both\n", audiohook);
00150       }
00151       ast_slinfactory_flush(factory);
00152       ast_slinfactory_flush(other_factory);
00153    }
00154 
00155    /* swap frame data for zeros if mute is required */
00156    if ((ast_test_flag(audiohook, AST_AUDIOHOOK_MUTE_READ) && (direction == AST_AUDIOHOOK_DIRECTION_READ)) ||
00157       (ast_test_flag(audiohook, AST_AUDIOHOOK_MUTE_WRITE) && (direction == AST_AUDIOHOOK_DIRECTION_WRITE)) ||
00158       (ast_test_flag(audiohook, AST_AUDIOHOOK_MUTE_READ | AST_AUDIOHOOK_MUTE_WRITE) == (AST_AUDIOHOOK_MUTE_READ | AST_AUDIOHOOK_MUTE_WRITE))) {
00159          muteme = 1;
00160    }
00161 
00162    if (muteme && frame->datalen > 0) {
00163       ast_frame_clear(frame);
00164    }
00165 
00166    /* Write frame out to respective factory */
00167    ast_slinfactory_feed(factory, frame);
00168 
00169    /* If we need to notify the respective handler of this audiohook, do so */
00170    if ((ast_test_flag(audiohook, AST_AUDIOHOOK_TRIGGER_MODE) == AST_AUDIOHOOK_TRIGGER_READ) && (direction == AST_AUDIOHOOK_DIRECTION_READ)) {
00171       ast_cond_signal(&audiohook->trigger);
00172    } else if ((ast_test_flag(audiohook, AST_AUDIOHOOK_TRIGGER_MODE) == AST_AUDIOHOOK_TRIGGER_WRITE) && (direction == AST_AUDIOHOOK_DIRECTION_WRITE)) {
00173       ast_cond_signal(&audiohook->trigger);
00174    } else if (ast_test_flag(audiohook, AST_AUDIOHOOK_TRIGGER_SYNC)) {
00175       ast_cond_signal(&audiohook->trigger);
00176    }
00177 
00178    return 0;
00179 }

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

00761 {
00762    /* Pass off frame to it's respective list write function */
00763    if (frame->frametype == AST_FRAME_VOICE)
00764       return audio_audiohook_write_list(chan, audiohook_list, direction, frame);
00765    else if (frame->frametype == AST_FRAME_DTMF)
00766       return dtmf_audiohook_write_list(chan, audiohook_list, direction, frame);
00767    else
00768       return frame;
00769 }

int ast_audiohook_write_list_empty ( struct ast_audiohook_list audiohook_list  ) 

determines if a audiohook_list is empty or not.

retval 0 false, 1 true

Definition at line 742 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_write(), and audio_audiohook_write_list().

00743 {
00744    if (AST_LIST_EMPTY(&audiohook_list->spy_list) &&
00745       AST_LIST_EMPTY(&audiohook_list->whisper_list) &&
00746       AST_LIST_EMPTY(&audiohook_list->manipulate_list)) {
00747 
00748       return 1;
00749    }
00750    return 0;
00751 }

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

References AST_AUDIOHOOK_TYPE_MANIPULATE, AST_AUDIOHOOK_TYPE_SPY, AST_AUDIOHOOK_TYPE_WHISPER, AST_LIST_TRAVERSE, ast_log(), ast_channel::audiohooks, ast_audiohook::list, ast_audiohook_list::manipulate_list, ast_audiohook::source, ast_audiohook_list::spy_list, and ast_audiohook_list::whisper_list.

Referenced by builtin_automixmonitor().

00790 {
00791    int count = 0;
00792    struct ast_audiohook *ah = NULL;
00793 
00794    if (!chan->audiohooks)
00795       return -1;
00796 
00797    switch (type) {
00798       case AST_AUDIOHOOK_TYPE_SPY:
00799          AST_LIST_TRAVERSE(&chan->audiohooks->spy_list, ah, list) {
00800             if (!strcmp(ah->source, source)) {
00801                count++;
00802             }
00803          }
00804          break;
00805       case AST_AUDIOHOOK_TYPE_WHISPER:
00806          AST_LIST_TRAVERSE(&chan->audiohooks->whisper_list, ah, list) {
00807             if (!strcmp(ah->source, source)) {
00808                count++;
00809             }
00810          }
00811          break;
00812       case AST_AUDIOHOOK_TYPE_MANIPULATE:
00813          AST_LIST_TRAVERSE(&chan->audiohooks->manipulate_list, ah, list) {
00814             if (!strcmp(ah->source, source)) {
00815                count++;
00816             }
00817          }
00818          break;
00819       default:
00820          ast_log(LOG_DEBUG, "Invalid audiohook type supplied, (%d)\n", type);
00821          return -1;
00822    }
00823 
00824    return count;
00825 }

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

References AST_AUDIOHOOK_STATUS_RUNNING, AST_AUDIOHOOK_TYPE_MANIPULATE, AST_AUDIOHOOK_TYPE_SPY, AST_AUDIOHOOK_TYPE_WHISPER, AST_LIST_TRAVERSE, ast_log(), ast_channel::audiohooks, ast_audiohook::list, ast_audiohook_list::manipulate_list, ast_audiohook::source, ast_audiohook_list::spy_list, ast_audiohook::status, and ast_audiohook_list::whisper_list.

Referenced by builtin_automixmonitor().

00829 {
00830    int count = 0;
00831    struct ast_audiohook *ah = NULL;
00832    if (!chan->audiohooks)
00833       return -1;
00834 
00835    switch (type) {
00836       case AST_AUDIOHOOK_TYPE_SPY:
00837          AST_LIST_TRAVERSE(&chan->audiohooks->spy_list, ah, list) {
00838             if ((!strcmp(ah->source, source)) && (ah->status == AST_AUDIOHOOK_STATUS_RUNNING))
00839                count++;
00840          }
00841          break;
00842       case AST_AUDIOHOOK_TYPE_WHISPER:
00843          AST_LIST_TRAVERSE(&chan->audiohooks->whisper_list, ah, list) {
00844             if ((!strcmp(ah->source, source)) && (ah->status == AST_AUDIOHOOK_STATUS_RUNNING))
00845                count++;
00846          }
00847          break;
00848       case AST_AUDIOHOOK_TYPE_MANIPULATE:
00849          AST_LIST_TRAVERSE(&chan->audiohooks->manipulate_list, ah, list) {
00850             if ((!strcmp(ah->source, source)) && (ah->status == AST_AUDIOHOOK_STATUS_RUNNING))
00851                count++;
00852          }
00853          break;
00854       default:
00855          ast_log(LOG_DEBUG, "Invalid audiohook type supplied, (%d)\n", type);
00856          return -1;
00857    }
00858    return count;
00859 }

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. The result of this part is end_frame will be updated to point to middle_frame if any audiohook manipulation took place. Part_3: Translate end_frame's audio back into the format of start frame if necessary. At this point if middle_frame != end_frame, we are guaranteed that no manipulation took place and middle_frame can be freed as it was translated... If middle_frame was not translated and still pointed to start_frame, it would be equal to end_frame as well regardless if manipulation took place which would not result in this free. The result of this part is end_frame is guaranteed to be the format of start_frame for the return.

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

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_audiohook_write_list_empty(), AST_FORMAT_SLINEAR, 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(), ast_translate(), ast_translator_build_path(), ast_translator_free_path(), ast_frame_subclass::codec, ast_audiohook_translate::format, ast_audiohook_list::in_translate, ast_audiohook::list, ast_audiohook::manipulate_callback, ast_audiohook_list::manipulate_list, ast_audiohook_list::out_translate, ast_frame::samples, ast_audiohook_list::spy_list, ast_audiohook::status, ast_frame::subclass, ast_audiohook_translate::trans_pvt, ast_audiohook_list::whisper_list, and ast_audiohook::write_factory.

Referenced by ast_audiohook_write_list().

00617 {
00618    struct ast_audiohook_translate *in_translate = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook_list->in_translate[0] : &audiohook_list->in_translate[1]);
00619    struct ast_audiohook_translate *out_translate = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook_list->out_translate[0] : &audiohook_list->out_translate[1]);
00620    struct ast_frame *start_frame = frame, *middle_frame = frame, *end_frame = frame;
00621    struct ast_audiohook *audiohook = NULL;
00622    int samples = frame->samples;
00623 
00624    /* Don't translate our frame if we aren't going to bother to use it */
00625    if (ast_audiohook_write_list_empty(audiohook_list))
00626       return end_frame;
00627 
00628    /* ---Part_1. translate start_frame to SLINEAR if necessary. */
00629    /* If the frame coming in is not signed linear we have to send it through the in_translate path */
00630    if (frame->subclass.codec != AST_FORMAT_SLINEAR) {
00631       if (in_translate->format != frame->subclass.codec) {
00632          if (in_translate->trans_pvt)
00633             ast_translator_free_path(in_translate->trans_pvt);
00634          if (!(in_translate->trans_pvt = ast_translator_build_path(AST_FORMAT_SLINEAR, frame->subclass.codec)))
00635             return frame;
00636          in_translate->format = frame->subclass.codec;
00637       }
00638       if (!(middle_frame = ast_translate(in_translate->trans_pvt, frame, 0)))
00639          return frame;
00640       samples = middle_frame->samples;
00641    }
00642 
00643    /* ---Part_2: Send middle_frame to spy and manipulator lists.  middle_frame is guaranteed to be SLINEAR here.*/
00644    /* Queue up signed linear frame to each spy */
00645    AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->spy_list, audiohook, list) {
00646       ast_audiohook_lock(audiohook);
00647       if (audiohook->status != AST_AUDIOHOOK_STATUS_RUNNING) {
00648          AST_LIST_REMOVE_CURRENT(list);
00649          ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_DONE);
00650          ast_audiohook_unlock(audiohook);
00651          continue;
00652       }
00653       ast_audiohook_write_frame(audiohook, direction, middle_frame);
00654       ast_audiohook_unlock(audiohook);
00655    }
00656    AST_LIST_TRAVERSE_SAFE_END;
00657 
00658    /* If this frame is being written out to the channel then we need to use whisper sources */
00659    if (direction == AST_AUDIOHOOK_DIRECTION_WRITE && !AST_LIST_EMPTY(&audiohook_list->whisper_list)) {
00660       int i = 0;
00661       short read_buf[samples], combine_buf[samples], *data1 = NULL, *data2 = NULL;
00662       memset(&combine_buf, 0, sizeof(combine_buf));
00663       AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->whisper_list, audiohook, list) {
00664          ast_audiohook_lock(audiohook);
00665          if (audiohook->status != AST_AUDIOHOOK_STATUS_RUNNING) {
00666             AST_LIST_REMOVE_CURRENT(list);
00667             ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_DONE);
00668             ast_audiohook_unlock(audiohook);
00669             continue;
00670          }
00671          if (ast_slinfactory_available(&audiohook->write_factory) >= samples && ast_slinfactory_read(&audiohook->write_factory, read_buf, samples)) {
00672             /* Take audio from this whisper source and combine it into our main buffer */
00673             for (i = 0, data1 = combine_buf, data2 = read_buf; i < samples; i++, data1++, data2++)
00674                ast_slinear_saturated_add(data1, data2);
00675          }
00676          ast_audiohook_unlock(audiohook);
00677       }
00678       AST_LIST_TRAVERSE_SAFE_END;
00679       /* We take all of the combined whisper sources and combine them into the audio being written out */
00680       for (i = 0, data1 = middle_frame->data.ptr, data2 = combine_buf; i < samples; i++, data1++, data2++)
00681          ast_slinear_saturated_add(data1, data2);
00682       end_frame = middle_frame;
00683    }
00684 
00685    /* Pass off frame to manipulate audiohooks */
00686    if (!AST_LIST_EMPTY(&audiohook_list->manipulate_list)) {
00687       AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->manipulate_list, audiohook, list) {
00688          ast_audiohook_lock(audiohook);
00689          if (audiohook->status != AST_AUDIOHOOK_STATUS_RUNNING) {
00690             AST_LIST_REMOVE_CURRENT(list);
00691             ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_DONE);
00692             ast_audiohook_unlock(audiohook);
00693             /* We basically drop all of our links to the manipulate audiohook and prod it to do it's own destructive things */
00694             audiohook->manipulate_callback(audiohook, chan, NULL, direction);
00695             continue;
00696          }
00697          /* Feed in frame to manipulation. */
00698          if (audiohook->manipulate_callback(audiohook, chan, middle_frame, direction)) {
00699             /* XXX IGNORE FAILURE */
00700 
00701             /* If the manipulation fails then the frame will be returned in its original state.
00702              * Since there are potentially more manipulator callbacks in the list, no action should
00703              * be taken here to exit early. */
00704          }
00705          ast_audiohook_unlock(audiohook);
00706       }
00707       AST_LIST_TRAVERSE_SAFE_END;
00708       end_frame = middle_frame;
00709    }
00710 
00711    /* ---Part_3: Decide what to do with the end_frame (whether to transcode or not) */
00712    if (middle_frame == end_frame) {
00713       /* Middle frame was modified and became the end frame... let's see if we need to transcode */
00714       if (end_frame->subclass.codec != start_frame->subclass.codec) {
00715          if (out_translate->format != start_frame->subclass.codec) {
00716             if (out_translate->trans_pvt)
00717                ast_translator_free_path(out_translate->trans_pvt);
00718             if (!(out_translate->trans_pvt = ast_translator_build_path(start_frame->subclass.codec, AST_FORMAT_SLINEAR))) {
00719                /* We can't transcode this... drop our middle frame and return the original */
00720                ast_frfree(middle_frame);
00721                return start_frame;
00722             }
00723             out_translate->format = start_frame->subclass.codec;
00724          }
00725          /* Transcode from our middle (signed linear) frame to new format of the frame that came in */
00726          if (!(end_frame = ast_translate(out_translate->trans_pvt, middle_frame, 0))) {
00727             /* Failed to transcode the frame... drop it and return the original */
00728             ast_frfree(middle_frame);
00729             return start_frame;
00730          }
00731          /* Here's the scoop... middle frame is no longer of use to us */
00732          ast_frfree(middle_frame);
00733       }
00734    } else {
00735       /* No frame was modified, we can just drop our middle frame and pass the frame we got in out */
00736       ast_frfree(middle_frame);
00737    }
00738 
00739    return end_frame;
00740 }

static struct ast_frame* audiohook_read_frame_both ( struct ast_audiohook audiohook,
size_t  samples 
) [static]

Definition at line 209 of file audiohook.c.

References ast_debug, AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_slinear_saturated_divide(), ast_slinear_saturated_multiply(), ast_slinfactory_available(), ast_slinfactory_read(), ast_tvdiff_ms(), ast_tvnow(), buf1, buf2, ast_frame::frametype, LOG_DEBUG, option_debug, ast_audiohook::options, ast_audiohook::read_factory, ast_audiohook::read_time, ast_audiohook_options::read_volume, ast_audiohook::write_factory, ast_audiohook::write_time, and ast_audiohook_options::write_volume.

Referenced by ast_audiohook_read_frame().

00210 {
00211    int i = 0, usable_read, usable_write;
00212    short buf1[samples], buf2[samples], *read_buf = NULL, *write_buf = NULL, *final_buf = NULL, *data1 = NULL, *data2 = NULL;
00213    struct ast_frame frame = {
00214       .frametype = AST_FRAME_VOICE,
00215       .subclass.codec = AST_FORMAT_SLINEAR,
00216       .data.ptr = NULL,
00217       .datalen = sizeof(buf1),
00218       .samples = samples,
00219    };
00220 
00221    /* Make sure both factories have the required samples */
00222    usable_read = (ast_slinfactory_available(&audiohook->read_factory) >= samples ? 1 : 0);
00223    usable_write = (ast_slinfactory_available(&audiohook->write_factory) >= samples ? 1 : 0);
00224 
00225    if (!usable_read && !usable_write) {
00226       /* If both factories are unusable bail out */
00227       ast_debug(1, "Read factory %p and write factory %p both fail to provide %zd samples\n", &audiohook->read_factory, &audiohook->write_factory, samples);
00228       return NULL;
00229    }
00230 
00231    /* If we want to provide only a read factory make sure we aren't waiting for other audio */
00232    if (usable_read && !usable_write && (ast_tvdiff_ms(ast_tvnow(), audiohook->write_time) < (samples/8)*2)) {
00233       ast_debug(3, "Write factory %p was pretty quick last time, waiting for them.\n", &audiohook->write_factory);
00234       return NULL;
00235    }
00236 
00237    /* If we want to provide only a write factory make sure we aren't waiting for other audio */
00238    if (usable_write && !usable_read && (ast_tvdiff_ms(ast_tvnow(), audiohook->read_time) < (samples/8)*2)) {
00239       ast_debug(3, "Read factory %p was pretty quick last time, waiting for them.\n", &audiohook->read_factory);
00240       return NULL;
00241    }
00242 
00243    /* Start with the read factory... if there are enough samples, read them in */
00244    if (usable_read) {
00245       if (ast_slinfactory_read(&audiohook->read_factory, buf1, samples)) {
00246          read_buf = buf1;
00247          /* Adjust read volume if need be */
00248          if (audiohook->options.read_volume) {
00249             int count = 0;
00250             short adjust_value = abs(audiohook->options.read_volume);
00251             for (count = 0; count < samples; count++) {
00252                if (audiohook->options.read_volume > 0)
00253                   ast_slinear_saturated_multiply(&buf1[count], &adjust_value);
00254                else if (audiohook->options.read_volume < 0)
00255                   ast_slinear_saturated_divide(&buf1[count], &adjust_value);
00256             }
00257          }
00258       }
00259    } else if (option_debug)
00260       ast_log(LOG_DEBUG, "Failed to get %d samples from read factory %p\n", (int)samples, &audiohook->read_factory);
00261 
00262    /* Move on to the write factory... if there are enough samples, read them in */
00263    if (usable_write) {
00264       if (ast_slinfactory_read(&audiohook->write_factory, buf2, samples)) {
00265          write_buf = buf2;
00266          /* Adjust write volume if need be */
00267          if (audiohook->options.write_volume) {
00268             int count = 0;
00269             short adjust_value = abs(audiohook->options.write_volume);
00270             for (count = 0; count < samples; count++) {
00271                if (audiohook->options.write_volume > 0)
00272                   ast_slinear_saturated_multiply(&buf2[count], &adjust_value);
00273                else if (audiohook->options.write_volume < 0)
00274                   ast_slinear_saturated_divide(&buf2[count], &adjust_value);
00275             }
00276          }
00277       }
00278    } else if (option_debug)
00279       ast_log(LOG_DEBUG, "Failed to get %d samples from write factory %p\n", (int)samples, &audiohook->write_factory);
00280 
00281    /* Basically we figure out which buffer to use... and if mixing can be done here */
00282    if (!read_buf && !write_buf)
00283       return NULL;
00284    else if (read_buf && write_buf) {
00285       for (i = 0, data1 = read_buf, data2 = write_buf; i < samples; i++, data1++, data2++)
00286          ast_slinear_saturated_add(data1, data2);
00287       final_buf = buf1;
00288    } else if (read_buf)
00289       final_buf = buf1;
00290    else if (write_buf)
00291       final_buf = buf2;
00292 
00293    /* Make the final buffer part of the frame, so it gets duplicated fine */
00294    frame.data.ptr = final_buf;
00295 
00296    /* Yahoo, a combined copy of the audio! */
00297    return ast_frdup(&frame);
00298 }

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

Definition at line 181 of file audiohook.c.

References AST_AUDIOHOOK_DIRECTION_READ, AST_FORMAT_SLINEAR, ast_frame_adjust_volume(), AST_FRAME_VOICE, ast_frdup(), ast_slinfactory_available(), ast_slinfactory_read(), ast_frame::frametype, ast_audiohook::options, ast_audiohook::read_factory, ast_audiohook_options::read_volume, ast_audiohook::write_factory, and ast_audiohook_options::write_volume.

Referenced by ast_audiohook_read_frame().

00182 {
00183    struct ast_slinfactory *factory = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook->read_factory : &audiohook->write_factory);
00184    int vol = (direction == AST_AUDIOHOOK_DIRECTION_READ ? audiohook->options.read_volume : audiohook->options.write_volume);
00185    short buf[samples];
00186    struct ast_frame frame = {
00187       .frametype = AST_FRAME_VOICE,
00188       .subclass.codec = AST_FORMAT_SLINEAR,
00189       .data.ptr = buf,
00190       .datalen = sizeof(buf),
00191       .samples = samples,
00192    };
00193 
00194    /* Ensure the factory is able to give us the samples we want */
00195    if (samples > ast_slinfactory_available(factory))
00196       return NULL;
00197    
00198    /* Read data in from factory */
00199    if (!ast_slinfactory_read(factory, buf, samples))
00200       return NULL;
00201 
00202    /* If a volume adjustment needs to be applied apply it */
00203    if (vol)
00204       ast_frame_adjust_volume(&frame, vol);
00205 
00206    return ast_frdup(&frame);
00207 }

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 898 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(), audiohook_volume::audiohook, audiohook_volume_datastore, ast_datastore::data, audiohook_volume::read_adjustment, ast_audiohook::status, and audiohook_volume::write_adjustment.

Referenced by audiohook_volume_get().

00899 {
00900    struct ast_datastore *datastore = NULL;
00901    struct audiohook_volume *audiohook_volume = NULL;
00902    int *gain = NULL;
00903 
00904    /* If the audiohook is shutting down don't even bother */
00905    if (audiohook->status == AST_AUDIOHOOK_STATUS_DONE) {
00906       return 0;
00907    }
00908 
00909    /* Try to find the datastore containg adjustment information, if we can't just bail out */
00910    if (!(datastore = ast_channel_datastore_find(chan, &audiohook_volume_datastore, NULL))) {
00911       return 0;
00912    }
00913 
00914    audiohook_volume = datastore->data;
00915 
00916    /* Based on direction grab the appropriate adjustment value */
00917    if (direction == AST_AUDIOHOOK_DIRECTION_READ) {
00918       gain = &audiohook_volume->read_adjustment;
00919    } else if (direction == AST_AUDIOHOOK_DIRECTION_WRITE) {
00920       gain = &audiohook_volume->write_adjustment;
00921    }
00922 
00923    /* If an adjustment value is present modify the frame */
00924    if (gain && *gain) {
00925       ast_frame_adjust_volume(frame, *gain);
00926    }
00927 
00928    return 0;
00929 }

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

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

00873 {
00874    struct audiohook_volume *audiohook_volume = data;
00875 
00876    /* Destroy the audiohook as it is no longer in use */
00877    ast_audiohook_destroy(&audiohook_volume->audiohook);
00878 
00879    /* Finally free ourselves, we are of no more use */
00880    ast_free(audiohook_volume);
00881 
00882    return;
00883 }

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

References ast_audiohook_attach(), ast_audiohook_init(), AST_AUDIOHOOK_TYPE_MANIPULATE, ast_calloc, ast_channel_datastore_add(), ast_channel_datastore_find(), ast_datastore_alloc, ast_datastore_free(), audiohook_volume_callback(), audiohook_volume_datastore, and ast_datastore::data.

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

00937 {
00938    struct ast_datastore *datastore = NULL;
00939    struct audiohook_volume *audiohook_volume = NULL;
00940 
00941    /* If we are able to find the datastore return the contents (which is actually an audiohook_volume structure) */
00942    if ((datastore = ast_channel_datastore_find(chan, &audiohook_volume_datastore, NULL))) {
00943       return datastore->data;
00944    }
00945 
00946    /* 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 */
00947    if (!create || !(datastore = ast_datastore_alloc(&audiohook_volume_datastore, NULL))) {
00948       return NULL;
00949    }
00950 
00951    /* Create a new audiohook_volume structure to contain our adjustments and audiohook */
00952    if (!(audiohook_volume = ast_calloc(1, sizeof(*audiohook_volume)))) {
00953       ast_datastore_free(datastore);
00954       return NULL;
00955    }
00956 
00957    /* Setup our audiohook structure so we can manipulate the audio */
00958    ast_audiohook_init(&audiohook_volume->audiohook, AST_AUDIOHOOK_TYPE_MANIPULATE, "Volume");
00959    audiohook_volume->audiohook.manipulate_callback = audiohook_volume_callback;
00960 
00961    /* Attach the audiohook_volume blob to the datastore and attach to the channel */
00962    datastore->data = audiohook_volume;
00963    ast_channel_datastore_add(chan, datastore);
00964 
00965    /* All is well... put the audiohook into motion */
00966    ast_audiohook_attach(chan, &audiohook_volume->audiohook);
00967 
00968    return audiohook_volume;
00969 }

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:
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 565 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_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_test_flag, ast_audiohook::list, ast_audiohook::manipulate_callback, ast_audiohook_list::manipulate_list, and ast_audiohook::status.

Referenced by ast_audiohook_write_list().

00566 {
00567    struct ast_audiohook *audiohook = NULL;
00568 
00569    AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->manipulate_list, audiohook, list) {
00570       ast_audiohook_lock(audiohook);
00571       if (audiohook->status != AST_AUDIOHOOK_STATUS_RUNNING) {
00572          AST_LIST_REMOVE_CURRENT(list);
00573          ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_DONE);
00574          ast_audiohook_unlock(audiohook);
00575          audiohook->manipulate_callback(audiohook, NULL, NULL, 0);
00576          continue;
00577       }
00578       if (ast_test_flag(audiohook, AST_AUDIOHOOK_WANTS_DTMF))
00579          audiohook->manipulate_callback(audiohook, chan, frame, direction);
00580       ast_audiohook_unlock(audiohook);
00581    }
00582    AST_LIST_TRAVERSE_SAFE_END;
00583 
00584    return frame;
00585 }

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

References AST_LIST_TRAVERSE, ast_audiohook::list, ast_audiohook_list::manipulate_list, 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().

00453 {
00454    struct ast_audiohook *audiohook = NULL;
00455 
00456    AST_LIST_TRAVERSE(&audiohook_list->spy_list, audiohook, list) {
00457       if (!strcasecmp(audiohook->source, source))
00458          return audiohook;
00459    }
00460 
00461    AST_LIST_TRAVERSE(&audiohook_list->whisper_list, audiohook, list) {
00462       if (!strcasecmp(audiohook->source, source))
00463          return audiohook;
00464    }
00465 
00466    AST_LIST_TRAVERSE(&audiohook_list->manipulate_list, audiohook, list) {
00467       if (!strcasecmp(audiohook->source, source))
00468          return audiohook;
00469    }
00470 
00471    return NULL;
00472 }


Variable Documentation

struct ast_datastore_info audiohook_volume_datastore [static]

Initial value:

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

Definition at line 886 of file audiohook.c.

Referenced by audiohook_volume_callback(), and audiohook_volume_get().


Generated on Mon Mar 19 11:30:36 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7