aboutsummaryrefslogtreecommitdiffstats
path: root/channel.c
diff options
context:
space:
mode:
authorkpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b>2006-07-28 18:59:59 +0000
committerkpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b>2006-07-28 18:59:59 +0000
commite2c714c0cff1a5c76c83a9b4280d5fad6ddae714 (patch)
treecc434c7447968461b0272d46631fd26fc0e9247a /channel.c
parent1b8e8e16331b3dc3ec079bc5a2e094c2fcac7f27 (diff)
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: http://svn.digium.com/svn/asterisk/trunk@38422 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channel.c')
-rw-r--r--channel.c86
1 files changed, 82 insertions, 4 deletions
diff --git a/channel.c b/channel.c
index 82eac1db1..d8b3e83ec 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;
+}