#include "asterisk/linkedlists.h"
Include dependency graph for chanspy.h:
This graph shows which files directly or indirectly include this file:
Go to the source code of this file.
Data Structures | |
struct | ast_channel_spy |
struct | ast_channel_spy_queue |
Enumerations | |
enum | chanspy_flags { CHANSPY_MIXAUDIO = (1 << 0), CHANSPY_READ_VOLADJUST = (1 << 1), CHANSPY_WRITE_VOLADJUST = (1 << 2), CHANSPY_FORMAT_AUDIO = (1 << 3), CHANSPY_TRIGGER_MODE = (3 << 4), CHANSPY_TRIGGER_READ = (1 << 4), CHANSPY_TRIGGER_WRITE = (2 << 4), CHANSPY_TRIGGER_NONE = (3 << 4), CHANSPY_TRIGGER_FLUSH = (1 << 6) } |
enum | chanspy_states { CHANSPY_NEW = 0, CHANSPY_RUNNING = 1, CHANSPY_DONE = 2, CHANSPY_STOP = 3 } |
Functions | |
int | ast_channel_spy_add (struct ast_channel *chan, struct ast_channel_spy *spy) |
Adds a spy to a channel, to begin receiving copies of the channel's audio frames. | |
ast_frame * | ast_channel_spy_read_frame (struct ast_channel_spy *spy, unsigned int samples) |
Read one (or more) frames of audio from a channel being spied upon. | |
void | ast_channel_spy_remove (struct ast_channel *chan, struct ast_channel_spy *spy) |
Remove a spy from a channel. | |
void | ast_channel_spy_stop_by_type (struct ast_channel *chan, const char *type) |
Find all spies of a particular type on a channel and stop them. | |
void | ast_channel_spy_trigger_wait (struct ast_channel_spy *spy) |
Efficiently wait until audio is available for a spy, or an exception occurs. |
Definition in file chanspy.h.
|
Definition at line 39 of file chanspy.h. 00039 { 00040 CHANSPY_MIXAUDIO = (1 << 0), 00041 CHANSPY_READ_VOLADJUST = (1 << 1), 00042 CHANSPY_WRITE_VOLADJUST = (1 << 2), 00043 CHANSPY_FORMAT_AUDIO = (1 << 3), 00044 CHANSPY_TRIGGER_MODE = (3 << 4), 00045 CHANSPY_TRIGGER_READ = (1 << 4), 00046 CHANSPY_TRIGGER_WRITE = (2 << 4), 00047 CHANSPY_TRIGGER_NONE = (3 << 4), 00048 CHANSPY_TRIGGER_FLUSH = (1 << 6), 00049 };
|
|
Definition at line 32 of file chanspy.h. 00032 { 00033 CHANSPY_NEW = 0, /*!< spy not yet operating */ 00034 CHANSPY_RUNNING = 1, /*!< normal operation, spy is still operating */ 00035 CHANSPY_DONE = 2, /*!< spy is stopped and already removed from channel */ 00036 CHANSPY_STOP = 3, /*!< spy requested to stop, still attached to channel */ 00037 };
|
|
Adds a spy to a channel, to begin receiving copies of the channel's audio frames.
Definition at line 965 of file channel.c. References ast_clear_flag, ast_cond_init(), AST_FORMAT_SLINEAR, ast_getformatname(), AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_HEAD, AST_LIST_INSERT_TAIL, ast_log(), ast_set_flag, ast_test_flag, calloc, CHANSPY_FORMAT_AUDIO, CHANSPY_MIXAUDIO, CHANSPY_READ_VOLADJUST, CHANSPY_TRIGGER_MODE, CHANSPY_TRIGGER_NONE, CHANSPY_TRIGGER_READ, CHANSPY_TRIGGER_WRITE, CHANSPY_WRITE_VOLADJUST, ast_channel_spy_queue::format, list, LOG_WARNING, ast_channel::name, ast_channel_spy::read_queue, ast_channel::spies, ast_channel_spy::trigger, ast_channel_spy::type, and ast_channel_spy::write_queue. Referenced by start_spying(), and startmon(). 00966 { 00967 if (!ast_test_flag(spy, CHANSPY_FORMAT_AUDIO)) { 00968 ast_log(LOG_WARNING, "Could not add channel spy '%s' to channel '%s', only audio format spies are supported.\n", 00969 spy->type, chan->name); 00970 return -1; 00971 } 00972 00973 if (ast_test_flag(spy, CHANSPY_READ_VOLADJUST) && (spy->read_queue.format != AST_FORMAT_SLINEAR)) { 00974 ast_log(LOG_WARNING, "Cannot provide volume adjustment on '%s' format spies\n", 00975 ast_getformatname(spy->read_queue.format)); 00976 return -1; 00977 } 00978 00979 if (ast_test_flag(spy, CHANSPY_WRITE_VOLADJUST) && (spy->write_queue.format != AST_FORMAT_SLINEAR)) { 00980 ast_log(LOG_WARNING, "Cannot provide volume adjustment on '%s' format spies\n", 00981 ast_getformatname(spy->write_queue.format)); 00982 return -1; 00983 } 00984 00985 if (ast_test_flag(spy, CHANSPY_MIXAUDIO) && 00986 ((spy->read_queue.format != AST_FORMAT_SLINEAR) || 00987 (spy->write_queue.format != AST_FORMAT_SLINEAR))) { 00988 ast_log(LOG_WARNING, "Cannot provide audio mixing on '%s'-'%s' format spies\n", 00989 ast_getformatname(spy->read_queue.format), ast_getformatname(spy->write_queue.format)); 00990 return -1; 00991 } 00992 00993 if (!chan->spies) { 00994 if (!(chan->spies = calloc(1, sizeof(*chan->spies)))) { 00995 ast_log(LOG_WARNING, "Memory allocation failure\n"); 00996 return -1; 00997 } 00998 00999 AST_LIST_HEAD_INIT_NOLOCK(&chan->spies->list); 01000 AST_LIST_INSERT_HEAD(&chan->spies->list, spy, list); 01001 } else { 01002 AST_LIST_INSERT_TAIL(&chan->spies->list, spy, list); 01003 } 01004 01005 if (ast_test_flag(spy, CHANSPY_TRIGGER_MODE) != CHANSPY_TRIGGER_NONE) { 01006 ast_cond_init(&spy->trigger, NULL); 01007 ast_set_flag(spy, CHANSPY_TRIGGER_READ); 01008 ast_clear_flag(spy, CHANSPY_TRIGGER_WRITE); 01009 } 01010 01011 ast_log(LOG_DEBUG, "Spy %s added to channel %s\n", 01012 spy->type, chan->name); 01013 01014 return 0; 01015 }
|
|
Read one (or more) frames of audio from a channel being spied upon.
Note: This function performs no locking; you must hold the spy's lock before calling this function. You must not hold the channel's lock at the same time. Definition at line 3855 of file channel.c. References ast_clear_flag, ast_codec_get_len(), ast_frame_adjust_volume(), ast_frame_slinear_sum(), AST_FRAME_VOICE, ast_frdup(), ast_frfree(), ast_test_flag, CHANSPY_MIXAUDIO, CHANSPY_READ_VOLADJUST, CHANSPY_TRIGGER_FLUSH, CHANSPY_WRITE_VOLADJUST, copy_data_from_queue(), ast_channel_spy_queue::format, ast_frame::frametype, ast_channel_spy_queue::head, ast_frame::next, ast_channel_spy::read_queue, ast_channel_spy::read_vol_adjustment, result, ast_frame::samples, ast_channel_spy_queue::samples, ast_channel_spy::write_queue, and ast_channel_spy::write_vol_adjustment. Referenced by mixmonitor_thread(), and spy_generate(). 03856 { 03857 struct ast_frame *result; 03858 /* buffers are allocated to hold SLINEAR, which is the largest format */ 03859 short read_buf[samples]; 03860 short write_buf[samples]; 03861 struct ast_frame *read_frame; 03862 struct ast_frame *write_frame; 03863 int need_dup; 03864 struct ast_frame stack_read_frame = { .frametype = AST_FRAME_VOICE, 03865 .subclass = spy->read_queue.format, 03866 .data = read_buf, 03867 .samples = samples, 03868 .datalen = ast_codec_get_len(spy->read_queue.format, samples), 03869 }; 03870 struct ast_frame stack_write_frame = { .frametype = AST_FRAME_VOICE, 03871 .subclass = spy->write_queue.format, 03872 .data = write_buf, 03873 .samples = samples, 03874 .datalen = ast_codec_get_len(spy->write_queue.format, samples), 03875 }; 03876 03877 /* if a flush has been requested, dump everything in whichever queue is larger */ 03878 if (ast_test_flag(spy, CHANSPY_TRIGGER_FLUSH)) { 03879 if (spy->read_queue.samples > spy->write_queue.samples) { 03880 if (ast_test_flag(spy, CHANSPY_READ_VOLADJUST)) { 03881 for (result = spy->read_queue.head; result; result = result->next) 03882 ast_frame_adjust_volume(result, spy->read_vol_adjustment); 03883 } 03884 result = spy->read_queue.head; 03885 spy->read_queue.head = NULL; 03886 spy->read_queue.samples = 0; 03887 ast_clear_flag(spy, CHANSPY_TRIGGER_FLUSH); 03888 return result; 03889 } else { 03890 if (ast_test_flag(spy, CHANSPY_WRITE_VOLADJUST)) { 03891 for (result = spy->write_queue.head; result; result = result->next) 03892 ast_frame_adjust_volume(result, spy->write_vol_adjustment); 03893 } 03894 result = spy->write_queue.head; 03895 spy->write_queue.head = NULL; 03896 spy->write_queue.samples = 0; 03897 ast_clear_flag(spy, CHANSPY_TRIGGER_FLUSH); 03898 return result; 03899 } 03900 } 03901 03902 if ((spy->read_queue.samples < samples) || (spy->write_queue.samples < samples)) 03903 return NULL; 03904 03905 /* short-circuit if both head frames have exactly what we want */ 03906 if ((spy->read_queue.head->samples == samples) && 03907 (spy->write_queue.head->samples == samples)) { 03908 read_frame = spy->read_queue.head; 03909 spy->read_queue.head = read_frame->next; 03910 read_frame->next = NULL; 03911 03912 write_frame = spy->write_queue.head; 03913 spy->write_queue.head = write_frame->next; 03914 write_frame->next = NULL; 03915 03916 spy->read_queue.samples -= samples; 03917 spy->write_queue.samples -= samples; 03918 03919 need_dup = 0; 03920 } else { 03921 copy_data_from_queue(&spy->read_queue, read_buf, samples); 03922 copy_data_from_queue(&spy->write_queue, write_buf, samples); 03923 03924 read_frame = &stack_read_frame; 03925 write_frame = &stack_write_frame; 03926 need_dup = 1; 03927 } 03928 03929 if (ast_test_flag(spy, CHANSPY_READ_VOLADJUST)) 03930 ast_frame_adjust_volume(read_frame, spy->read_vol_adjustment); 03931 03932 if (ast_test_flag(spy, CHANSPY_WRITE_VOLADJUST)) 03933 ast_frame_adjust_volume(write_frame, spy->write_vol_adjustment); 03934 03935 if (ast_test_flag(spy, CHANSPY_MIXAUDIO)) { 03936 ast_frame_slinear_sum(read_frame, write_frame); 03937 03938 if (need_dup) 03939 result = ast_frdup(read_frame); 03940 else { 03941 result = read_frame; 03942 ast_frfree(write_frame); 03943 } 03944 } else { 03945 if (need_dup) { 03946 result = ast_frdup(read_frame); 03947 result->next = ast_frdup(write_frame); 03948 } else { 03949 result = read_frame; 03950 result->next = write_frame; 03951 } 03952 } 03953 03954 return result; 03955 }
|
|
|
Find all spies of a particular type on a channel and stop them.
Definition at line 1017 of file channel.c. References ast_cond_signal(), AST_LIST_TRAVERSE, ast_mutex_lock(), ast_mutex_unlock(), ast_test_flag, CHANSPY_RUNNING, CHANSPY_STOP, CHANSPY_TRIGGER_MODE, CHANSPY_TRIGGER_NONE, list, ast_channel_spy::lock, ast_channel::spies, ast_channel_spy::status, ast_channel_spy::trigger, and ast_channel_spy::type. Referenced by mixmonitor_cli(). 01018 { 01019 struct ast_channel_spy *spy; 01020 01021 if (!chan->spies) 01022 return; 01023 01024 AST_LIST_TRAVERSE(&chan->spies->list, spy, list) { 01025 ast_mutex_lock(&spy->lock); 01026 if ((spy->type == type) && (spy->status == CHANSPY_RUNNING)) { 01027 spy->status = CHANSPY_STOP; 01028 if (ast_test_flag(spy, CHANSPY_TRIGGER_MODE) != CHANSPY_TRIGGER_NONE) 01029 ast_cond_signal(&spy->trigger); 01030 } 01031 ast_mutex_unlock(&spy->lock); 01032 } 01033 }
|
|
Efficiently wait until audio is available for a spy, or an exception occurs.
Definition at line 1035 of file channel.c. References ast_cond_wait(), ast_channel_spy::lock, and ast_channel_spy::trigger. Referenced by mixmonitor_thread(). 01036 { 01037 ast_cond_wait(&spy->trigger, &spy->lock); 01038 }
|