mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-19 11:42:27 +00:00
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
This commit is contained in:
86
channel.c
86
channel.c
@@ -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;
|
||||||
|
}
|
||||||
|
2
frame.c
2
frame.c
@@ -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));
|
||||||
|
Reference in New Issue
Block a user