OPTION_EXIT = (1 << 8), /* Exit to a valid single digit extension */
OPTION_ENFORCED = (1 << 9), /* Enforced mode */
OPTION_NOTECH = (1 << 10), /* Skip technology name playback */
+ OPTION_BARGE = (1 << 11), /* Barge mode (whisper to both channels) */
} chanspy_opt_flags;
enum {
AST_APP_OPTIONS(spy_opts, {
AST_APP_OPTION('q', OPTION_QUIET),
AST_APP_OPTION('b', OPTION_BRIDGED),
+ AST_APP_OPTION('B', OPTION_BARGE),
AST_APP_OPTION('w', OPTION_WHISPER),
AST_APP_OPTION('W', OPTION_PRIVATE),
AST_APP_OPTION_ARG('v', OPTION_VOLUME, OPT_ARG_VOLUME),
/* spy data */
struct ast_audiohook spy_audiohook;
struct ast_audiohook whisper_audiohook;
+ struct ast_audiohook bridge_whisper_audiohook;
int fd;
int volfactor;
};
.generate = spy_generate,
};
-static int start_spying(struct ast_channel *chan, const char *spychan_name, struct ast_audiohook *audiohook)
+static int start_spying(struct ast_channel *chan, const char *spychan_name, struct ast_audiohook *audiohook)
{
int res = 0;
struct ast_channel *peer = NULL;
return 0;
}
- if (ast_test_flag(flags, OPTION_WHISPER)) {
+ if (ast_test_flag(flags, OPTION_BARGE)) {
+ ast_audiohook_init(&csth.whisper_audiohook, AST_AUDIOHOOK_TYPE_WHISPER, "ChanSpy");
+ ast_audiohook_init(&csth.bridge_whisper_audiohook, AST_AUDIOHOOK_TYPE_WHISPER, "Chanspy");
+ start_spying(spyee, spyer_name, &csth.whisper_audiohook); /* Unlocks spyee */
+ start_spying(ast_bridged_channel(spyee), spyer_name, &csth.bridge_whisper_audiohook);
+ } else if (ast_test_flag(flags, OPTION_WHISPER)) {
ast_audiohook_init(&csth.whisper_audiohook, AST_AUDIOHOOK_TYPE_WHISPER, "ChanSpy");
- start_spying(spyee, spyer_name, &csth.whisper_audiohook);
- }
+ start_spying(spyee, spyer_name, &csth.whisper_audiohook); /* Unlocks spyee */
+ }
ast_channel_unlock(spyee);
spyee = NULL;
break;
}
- if (ast_test_flag(flags, OPTION_WHISPER) && f->frametype == AST_FRAME_VOICE) {
+ if (ast_test_flag(flags, OPTION_BARGE) && f->frametype == AST_FRAME_VOICE) {
+ ast_audiohook_lock(&csth.whisper_audiohook);
+ ast_audiohook_lock(&csth.bridge_whisper_audiohook);
+ ast_audiohook_write_frame(&csth.whisper_audiohook, AST_AUDIOHOOK_DIRECTION_WRITE, f);
+ ast_audiohook_write_frame(&csth.bridge_whisper_audiohook, AST_AUDIOHOOK_DIRECTION_WRITE, f);
+ ast_audiohook_unlock(&csth.whisper_audiohook);
+ ast_audiohook_unlock(&csth.bridge_whisper_audiohook);
+ ast_frfree(f);
+ continue;
+ } else if (ast_test_flag(flags, OPTION_WHISPER) && f->frametype == AST_FRAME_VOICE) {
ast_audiohook_lock(&csth.whisper_audiohook);
ast_audiohook_write_frame(&csth.whisper_audiohook, AST_AUDIOHOOK_DIRECTION_WRITE, f);
ast_audiohook_unlock(&csth.whisper_audiohook);
else
ast_deactivate_generator(chan);
- if (ast_test_flag(flags, OPTION_WHISPER)) {
+ if (ast_test_flag(flags, OPTION_BARGE)) {
+ ast_audiohook_lock(&csth.whisper_audiohook);
+ ast_audiohook_detach(&csth.whisper_audiohook);
+ ast_audiohook_unlock(&csth.whisper_audiohook);
+ ast_audiohook_destroy(&csth.whisper_audiohook);
+ ast_audiohook_lock(&csth.bridge_whisper_audiohook);
+ ast_audiohook_detach(&csth.bridge_whisper_audiohook);
+ ast_audiohook_unlock(&csth.bridge_whisper_audiohook);
+ ast_audiohook_destroy(&csth.bridge_whisper_audiohook);
+ } else if (ast_test_flag(flags, OPTION_WHISPER)) {
ast_audiohook_lock(&csth.whisper_audiohook);
ast_audiohook_detach(&csth.whisper_audiohook);
ast_audiohook_unlock(&csth.whisper_audiohook);