Thu Sep 7 01:03:13 2017

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

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

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

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

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

00402 {
00403    if (audiohook->status == AST_AUDIOHOOK_STATUS_NEW || audiohook->status == AST_AUDIOHOOK_STATUS_DONE)
00404       return 0;
00405 
00406    ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_SHUTDOWN);
00407 
00408    while (audiohook->status != AST_AUDIOHOOK_STATUS_DONE)
00409       ast_audiohook_trigger_wait(audiohook);
00410 
00411    return 0;
00412 }

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 418 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::manipulate_callback, 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_write(), and destroy_hooks().

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

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

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

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

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

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

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

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

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 313 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(), ast_audiohook::format, read_frame(), and ast_audiohook::trans_pvt.

Referenced by mixmonitor_thread(), and spy_generate().

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

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

00542 {
00543    ast_channel_lock(chan);
00544 
00545    if (!chan->audiohooks) {
00546       ast_channel_unlock(chan);
00547       return -1;
00548    }
00549 
00550    if (audiohook->type == AST_AUDIOHOOK_TYPE_SPY)
00551       AST_LIST_REMOVE(&chan->audiohooks->spy_list, audiohook, list);
00552    else if (audiohook->type == AST_AUDIOHOOK_TYPE_WHISPER)
00553       AST_LIST_REMOVE(&chan->audiohooks->whisper_list, audiohook, list);
00554    else if (audiohook->type == AST_AUDIOHOOK_TYPE_MANIPULATE)
00555       AST_LIST_REMOVE(&chan->audiohooks->manipulate_list, audiohook, list);
00556 
00557    ast_audiohook_update_status(audiohook, AST_AUDIOHOOK_STATUS_DONE);
00558 
00559    ast_channel_unlock(chan);
00560 
00561    return 0;
00562 }

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

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

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

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

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

00388 {
00389    ast_audiohook_lock(audiohook);
00390    if (audiohook->status != AST_AUDIOHOOK_STATUS_DONE) {
00391       audiohook->status = status;
00392       ast_cond_signal(&audiohook->trigger);
00393    }
00394    ast_audiohook_unlock(audiohook);
00395 }

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

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

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

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

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

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

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

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

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

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

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

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

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

Referenced by builtin_automixmonitor().

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

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 830 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, LOG_DEBUG, 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().

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

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

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

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

Definition at line 215 of file audiohook.c.

References ast_debug, AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_frdup(), ast_log(), ast_slinear_saturated_add(), ast_slinear_saturated_divide(), ast_slinear_saturated_multiply(), ast_slinfactory_available(), ast_slinfactory_read(), ast_tvdiff_ms(), ast_tvnow(), ast_frame::data, ast_frame::frametype, LOG_DEBUG, option_debug, ast_audiohook::options, ast_frame::ptr, 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().

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

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

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

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 900 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, audiohook_volume::read_adjustment, ast_audiohook::status, and audiohook_volume::write_adjustment.

Referenced by audiohook_volume_get().

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

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

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

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

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

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

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

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 571 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::manipulate_callback, ast_audiohook_list::manipulate_list, and ast_audiohook::status.

Referenced by ast_audiohook_write_list().

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

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

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

00459 {
00460    struct ast_audiohook *audiohook = NULL;
00461 
00462    AST_LIST_TRAVERSE(&audiohook_list->spy_list, audiohook, list) {
00463       if (!strcasecmp(audiohook->source, source))
00464          return audiohook;
00465    }
00466 
00467    AST_LIST_TRAVERSE(&audiohook_list->whisper_list, audiohook, list) {
00468       if (!strcasecmp(audiohook->source, source))
00469          return audiohook;
00470    }
00471 
00472    AST_LIST_TRAVERSE(&audiohook_list->manipulate_list, audiohook, list) {
00473       if (!strcasecmp(audiohook->source, source))
00474          return audiohook;
00475    }
00476 
00477    return NULL;
00478 }


Variable Documentation

Initial value:
 {
   .type = "Volume",
   .destroy = audiohook_volume_destroy,
}

Datastore used to store audiohook volume information.

Definition at line 888 of file audiohook.c.


Generated on 7 Sep 2017 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1