From 3314ea0d59e6372b05034d6a43aa8ef848999b74 Mon Sep 17 00:00:00 2001 From: "Kevin P. Fleming" <kpfleming@digium.com> Date: Fri, 28 Jul 2006 18:59:59 +0000 Subject: [PATCH] move slinfactory structure definition back to header... it's just easier to use this way add infrastructure for whispering onto a channel git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@38422 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- channel.c | 86 ++++++++++++++++++++++++++++++++-- frame.c | 2 +- include/asterisk/channel.h | 45 +++++++++++++++--- include/asterisk/frame.h | 6 +-- include/asterisk/slinfactory.h | 10 +++- slinfactory.c | 10 ---- 6 files changed, 134 insertions(+), 25 deletions(-) diff --git a/channel.c b/channel.c index 82eac1db14..d8b3e83ecb 100644 --- a/channel.c +++ b/channel.c @@ -66,6 +66,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/transcap.h" #include "asterisk/devicestate.h" #include "asterisk/sha1.h" +#include "asterisk/slinfactory.h" struct channel_spy_trans { int last_format; @@ -78,6 +79,12 @@ struct ast_channel_spy_list { AST_LIST_HEAD_NOLOCK(, ast_channel_spy) list; }; +struct ast_channel_whisper_buffer { + ast_mutex_t lock; + struct ast_slinfactory sf; + unsigned int original_format; +}; + /* uncomment if you have problems with 'monitoring' synchronized files */ #if 0 #define MONITOR_CONSTANT_DELAY @@ -987,14 +994,17 @@ void ast_channel_free(struct ast_channel *chan) ast_copy_string(name, chan->name, sizeof(name)); /* Stop monitoring */ - if (chan->monitor) { + if (chan->monitor) chan->monitor->stop( chan, 0 ); - } /* If there is native format music-on-hold state, free it */ - if(chan->music_state) + if (chan->music_state) ast_moh_cleanup(chan); + /* if someone is whispering on the channel, stop them */ + if (chan->whisper) + ast_channel_whisper_stop(chan); + /* Free translators */ if (chan->readtrans) ast_translator_free_path(chan->readtrans); @@ -2445,6 +2455,25 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr) } } + if (ast_test_flag(chan, AST_FLAG_WHISPER)) { + /* frame is assumed to be in SLINEAR, since that is + required for whisper mode */ + ast_frame_adjust_volume(f, -2); + if (ast_slinfactory_available(&chan->whisper->sf) >= f->samples) { + short buf[f->samples]; + struct ast_frame whisper = { + .frametype = AST_FRAME_VOICE, + .subclass = AST_FORMAT_SLINEAR, + .data = buf, + .datalen = sizeof(buf), + .samples = f->samples, + }; + + if (ast_slinfactory_read(&chan->whisper->sf, buf, f->samples)) + ast_frame_slinear_sum(f, &whisper); + } + } + res = chan->tech->write(chan, f); } break; @@ -3171,6 +3200,16 @@ int ast_do_masquerade(struct ast_channel *original) if (x != AST_GENERATOR_FD) original->fds[x] = clone->fds[x]; } + + /* move any whisperer over */ + ast_channel_whisper_stop(original); + if (ast_test_flag(clone, AST_FLAG_WHISPER)) { + original->whisper = clone->whisper; + ast_set_flag(original, AST_FLAG_WHISPER); + clone->whisper = NULL; + ast_clear_flag(clone, AST_FLAG_WHISPER); + } + /* Move data stores over */ if (AST_LIST_FIRST(&clone->datastores)) AST_LIST_INSERT_TAIL(&original->datastores, AST_LIST_FIRST(&clone->datastores), entry); @@ -4401,4 +4440,43 @@ int ast_say_digits_full(struct ast_channel *chan, int num, return ast_say_digit_str_full(chan, buf, ints, lang, audiofd, ctrlfd); } -/* end of file */ +int ast_channel_whisper_start(struct ast_channel *chan) +{ + if (chan->whisper) + return -1; + + if (!(chan->whisper = ast_calloc(1, sizeof(*chan->whisper)))) + return -1; + + ast_mutex_init(&chan->whisper->lock); + ast_slinfactory_init(&chan->whisper->sf); + chan->whisper->original_format = ast_set_write_format(chan, AST_FORMAT_SLINEAR); + ast_set_flag(chan, AST_FLAG_WHISPER); + + return 0; +} + +int ast_channel_whisper_feed(struct ast_channel *chan, struct ast_frame *f) +{ + if (!chan->whisper) + return -1; + + ast_mutex_lock(&chan->whisper->lock); + ast_slinfactory_feed(&chan->whisper->sf, f); + ast_mutex_unlock(&chan->whisper->lock); + + return 0; +} + +void ast_channel_whisper_stop(struct ast_channel *chan) +{ + if (!chan->whisper) + return; + + ast_clear_flag(chan, AST_FLAG_WHISPER); + ast_set_write_format(chan, chan->whisper->original_format); + ast_slinfactory_destroy(&chan->whisper->sf); + ast_mutex_destroy(&chan->whisper->lock); + free(chan->whisper); + chan->whisper = NULL; +} diff --git a/frame.c b/frame.c index 62d69eda1d..ac1c72e05c 100644 --- a/frame.c +++ b/frame.c @@ -359,7 +359,7 @@ struct ast_frame *ast_frisolate(struct ast_frame *fr) return out; } -struct ast_frame *ast_frdup(struct ast_frame *f) +struct ast_frame *ast_frdup(const struct ast_frame *f) { struct ast_frame *out; int len, srclen = 0; diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index 06a895293c..fe2b33ed90 100644 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -268,6 +268,7 @@ struct ast_channel_tech { }; struct ast_channel_spy_list; +struct ast_channel_whisper_buffer; #define DEBUGCHAN_FLAG 0x80000000 #define FRAMECOUNT_INC(x) ( ((x) & DEBUGCHAN_FLAG) | ((x++) & ~DEBUGCHAN_FLAG) ) @@ -382,6 +383,7 @@ struct ast_channel { int rawwriteformat; /*!< Raw write format */ struct ast_channel_spy_list *spies; /*!< Chan Spy stuff */ + struct ast_channel_whisper_buffer *whisper; /*!< Whisper Paging buffer */ AST_LIST_ENTRY(ast_channel) chan_list; /*!< For easy linking */ struct ast_jb jb; /*!< The jitterbuffer state */ @@ -397,21 +399,20 @@ struct ast_channel { /*! \brief Channels have this property if they can create jitter; i.e. most VoIP channels */ #define AST_CHAN_TP_CREATESJITTER (1 << 1) -/* This flag has been deprecated by the transfercapbilty data member in struct ast_channel */ -/* #define AST_FLAG_DIGITAL (1 << 0) */ /* if the call is a digital ISDN call */ #define AST_FLAG_DEFER_DTMF (1 << 1) /*!< if dtmf should be deferred */ #define AST_FLAG_WRITE_INT (1 << 2) /*!< if write should be interrupt generator */ #define AST_FLAG_BLOCKING (1 << 3) /*!< if we are blocking */ #define AST_FLAG_ZOMBIE (1 << 4) /*!< if we are a zombie */ #define AST_FLAG_EXCEPTION (1 << 5) /*!< if there is a pending exception */ #define AST_FLAG_MOH (1 << 6) /*!< XXX anthm promises me this will disappear XXX listening to moh */ -#define AST_FLAG_SPYING (1 << 7) /*!< XXX might also go away XXX is spying on someone */ +#define AST_FLAG_SPYING (1 << 7) /*!< is spying on someone */ #define AST_FLAG_NBRIDGE (1 << 8) /*!< is it in a native bridge */ #define AST_FLAG_IN_AUTOLOOP (1 << 9) /*!< the channel is in an auto-incrementing dialplan processor, so when ->priority is set, it will get incremented before - finding the next priority to run - */ -#define AST_FLAG_OUTGOING (1 << 10) /*! Is this call outgoing */ + finding the next priority to run */ +#define AST_FLAG_OUTGOING (1 << 10) /*!< Is this call outgoing */ +#define AST_FLAG_WHISPER (1 << 11) /*!< Is this channel being whispered on */ + /* @} */ #define AST_FEATURE_PLAY_WARNING (1 << 0) @@ -1277,6 +1278,38 @@ const char *channelreloadreason2txt(enum channelreloadreason reason); /*! \brief return an ast_variable list of channeltypes */ struct ast_variable *ast_channeltype_list(void); +/*! + \brief Begin 'whispering' onto a channel + \param chan The channel to whisper onto + \return 0 for success, non-zero for failure + + This function will add a whisper buffer onto a channel and set a flag + causing writes to the channel to reduce the volume level of the written + audio samples, and then to mix in audio from the whisper buffer if it + is available. + + Note: This function performs no locking; you must hold the channel's lock before + calling this function. + */ +int ast_channel_whisper_start(struct ast_channel *chan); + +/*! + \brief Feed an audio frame into the whisper buffer on a channel + \param chan The channel to whisper onto + \return 0 for success, non-zero for failure + */ +int ast_channel_whisper_feed(struct ast_channel *chan, struct ast_frame *f); + +/*! + \brief Stop 'whispering' onto a channel + \param chan The channel to whisper onto + \return 0 for success, non-zero for failure + + Note: This function performs no locking; you must hold the channel's lock before + calling this function. + */ +void ast_channel_whisper_stop(struct ast_channel *chan); + #if defined(__cplusplus) || defined(c_plusplus) } #endif diff --git a/include/asterisk/frame.h b/include/asterisk/frame.h index ab9cb1b8c1..35cd30ac6c 100644 --- a/include/asterisk/frame.h +++ b/include/asterisk/frame.h @@ -354,7 +354,7 @@ struct ast_frame *ast_fralloc(char *source, int len); */ void ast_frfree(struct ast_frame *fr); -/*! \brief Copies a frame +/*! \brief Makes a frame independent of any static storage * \param fr frame to act upon * Take a frame, and if it's not been malloc'd, make a malloc'd copy * and if the data hasn't been malloced then make the @@ -366,10 +366,10 @@ struct ast_frame *ast_frisolate(struct ast_frame *fr); /*! \brief Copies a frame * \param fr frame to copy - * Dupliates a frame -- should only rarely be used, typically frisolate is good enough + * Duplicates a frame -- should only rarely be used, typically frisolate is good enough * \return Returns a frame on success, NULL on error */ -struct ast_frame *ast_frdup(struct ast_frame *fr); +struct ast_frame *ast_frdup(const struct ast_frame *fr); /*! \brief Reads a frame from an fd * Read a frame from a stream or packet fd, as written by fd_write diff --git a/include/asterisk/slinfactory.h b/include/asterisk/slinfactory.h index be2e96e58d..4bdbfa7cdf 100644 --- a/include/asterisk/slinfactory.h +++ b/include/asterisk/slinfactory.h @@ -31,7 +31,15 @@ extern "C" { #endif -struct ast_slinfactory; +struct ast_slinfactory { + struct ast_frame *queue; + struct ast_trans_pvt *trans; + short hold[1280]; + short *offset; + size_t holdlen; /*!< in samples */ + unsigned int size; /*!< in samples */ + unsigned int format; +}; void ast_slinfactory_init(struct ast_slinfactory *sf); void ast_slinfactory_destroy(struct ast_slinfactory *sf); diff --git a/slinfactory.c b/slinfactory.c index 632187ccbd..62a863d87d 100644 --- a/slinfactory.c +++ b/slinfactory.c @@ -35,16 +35,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/logger.h" #include "asterisk/translate.h" -struct ast_slinfactory { - struct ast_frame *queue; - struct ast_trans_pvt *trans; - short hold[1280]; - short *offset; - size_t holdlen; /*! in samples */ - unsigned int size; /*! in samples */ - unsigned int format; -}; - void ast_slinfactory_init(struct ast_slinfactory *sf) { memset(sf, 0, sizeof(*sf)); -- GitLab