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
1.4
Kevin P. Fleming 19 years ago
parent 48c09ef517
commit 3314ea0d59

@ -66,6 +66,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/transcap.h" #include "asterisk/transcap.h"
#include "asterisk/devicestate.h" #include "asterisk/devicestate.h"
#include "asterisk/sha1.h" #include "asterisk/sha1.h"
#include "asterisk/slinfactory.h"
struct channel_spy_trans { struct channel_spy_trans {
int last_format; int last_format;
@ -78,6 +79,12 @@ struct ast_channel_spy_list {
AST_LIST_HEAD_NOLOCK(, 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 */ /* uncomment if you have problems with 'monitoring' synchronized files */
#if 0 #if 0
#define MONITOR_CONSTANT_DELAY #define MONITOR_CONSTANT_DELAY
@ -987,14 +994,17 @@ void ast_channel_free(struct ast_channel *chan)
ast_copy_string(name, chan->name, sizeof(name)); ast_copy_string(name, chan->name, sizeof(name));
/* Stop monitoring */ /* Stop monitoring */
if (chan->monitor) { if (chan->monitor)
chan->monitor->stop( chan, 0 ); chan->monitor->stop( chan, 0 );
}
/* If there is native format music-on-hold state, free it */ /* If there is native format music-on-hold state, free it */
if(chan->music_state) if (chan->music_state)
ast_moh_cleanup(chan); ast_moh_cleanup(chan);
/* if someone is whispering on the channel, stop them */
if (chan->whisper)
ast_channel_whisper_stop(chan);
/* Free translators */ /* Free translators */
if (chan->readtrans) if (chan->readtrans)
ast_translator_free_path(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); res = chan->tech->write(chan, f);
} }
break; break;
@ -3171,6 +3200,16 @@ int ast_do_masquerade(struct ast_channel *original)
if (x != AST_GENERATOR_FD) if (x != AST_GENERATOR_FD)
original->fds[x] = clone->fds[x]; 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 */ /* Move data stores over */
if (AST_LIST_FIRST(&clone->datastores)) if (AST_LIST_FIRST(&clone->datastores))
AST_LIST_INSERT_TAIL(&original->datastores, AST_LIST_FIRST(&clone->datastores), entry); 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); 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;
}

@ -359,7 +359,7 @@ struct ast_frame *ast_frisolate(struct ast_frame *fr)
return out; 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; struct ast_frame *out;
int len, srclen = 0; int len, srclen = 0;

@ -268,6 +268,7 @@ struct ast_channel_tech {
}; };
struct ast_channel_spy_list; struct ast_channel_spy_list;
struct ast_channel_whisper_buffer;
#define DEBUGCHAN_FLAG 0x80000000 #define DEBUGCHAN_FLAG 0x80000000
#define FRAMECOUNT_INC(x) ( ((x) & DEBUGCHAN_FLAG) | ((x++) & ~DEBUGCHAN_FLAG) ) #define FRAMECOUNT_INC(x) ( ((x) & DEBUGCHAN_FLAG) | ((x++) & ~DEBUGCHAN_FLAG) )
@ -382,6 +383,7 @@ struct ast_channel {
int rawwriteformat; /*!< Raw write format */ int rawwriteformat; /*!< Raw write format */
struct ast_channel_spy_list *spies; /*!< Chan Spy stuff */ 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 */ AST_LIST_ENTRY(ast_channel) chan_list; /*!< For easy linking */
struct ast_jb jb; /*!< The jitterbuffer state */ 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 */ /*! \brief Channels have this property if they can create jitter; i.e. most VoIP channels */
#define AST_CHAN_TP_CREATESJITTER (1 << 1) #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_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_WRITE_INT (1 << 2) /*!< if write should be interrupt generator */
#define AST_FLAG_BLOCKING (1 << 3) /*!< if we are blocking */ #define AST_FLAG_BLOCKING (1 << 3) /*!< if we are blocking */
#define AST_FLAG_ZOMBIE (1 << 4) /*!< if we are a zombie */ #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_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_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_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, #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 so when ->priority is set, it will get incremented before
finding the next priority to run finding the next priority to run */
*/ #define AST_FLAG_OUTGOING (1 << 10) /*!< Is this call outgoing */
#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) #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 */ /*! \brief return an ast_variable list of channeltypes */
struct ast_variable *ast_channeltype_list(void); 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) #if defined(__cplusplus) || defined(c_plusplus)
} }
#endif #endif

@ -354,7 +354,7 @@ struct ast_frame *ast_fralloc(char *source, int len);
*/ */
void ast_frfree(struct ast_frame *fr); 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 * \param fr frame to act upon
* Take a frame, and if it's not been malloc'd, make a malloc'd copy * 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 * 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 /*! \brief Copies a frame
* \param fr frame to copy * \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 * \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 /*! \brief Reads a frame from an fd
* Read a frame from a stream or packet fd, as written by fd_write * Read a frame from a stream or packet fd, as written by fd_write

@ -31,7 +31,15 @@
extern "C" { extern "C" {
#endif #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_init(struct ast_slinfactory *sf);
void ast_slinfactory_destroy(struct ast_slinfactory *sf); void ast_slinfactory_destroy(struct ast_slinfactory *sf);

@ -35,16 +35,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/logger.h" #include "asterisk/logger.h"
#include "asterisk/translate.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) void ast_slinfactory_init(struct ast_slinfactory *sf)
{ {
memset(sf, 0, sizeof(*sf)); memset(sf, 0, sizeof(*sf));

Loading…
Cancel
Save