diff options
author | markster <markster@f38db490-d61c-443f-a65b-d21fe96a405b> | 1999-11-12 23:51:16 +0000 |
---|---|---|
committer | markster <markster@f38db490-d61c-443f-a65b-d21fe96a405b> | 1999-11-12 23:51:16 +0000 |
commit | 4008ff118995ec2b42e78d85ee3ac9fec60371b9 (patch) | |
tree | fe685ef835a6f0991d845f3e4be90294e43716eb /apps/app_intercom.c | |
parent | c807c3d28c9cb233eaabf771dc9bf420f9fccc5e (diff) |
Version 0.1.0 from FTP
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@17 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'apps/app_intercom.c')
-rwxr-xr-x | apps/app_intercom.c | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/apps/app_intercom.c b/apps/app_intercom.c new file mode 100755 index 000000000..cf078b70a --- /dev/null +++ b/apps/app_intercom.c @@ -0,0 +1,189 @@ +/* + * Asterisk -- A telephony toolkit for Linux. + * + * Use /dev/dsp as an intercom. + * + * Copyright (C) 1999, Adtran Inc. and Linux Support Services, LLC + * + * Mark Spencer <markster@linux-support.net> + * + * This program is free software, distributed under the terms of + * the GNU General Public License + */ + +#include <asterisk/file.h> +#include <asterisk/frame.h> +#include <asterisk/logger.h> +#include <asterisk/channel.h> +#include <asterisk/pbx.h> +#include <asterisk/module.h> +#include <asterisk/translate.h> +#include <unistd.h> +#include <errno.h> +#include <sys/ioctl.h> +#include <string.h> +#include <stdlib.h> +#include <pthread.h> +#include <sys/time.h> +#include <linux/soundcard.h> +#include <netinet/in.h> + +#define DEV_DSP "/dev/dsp" + +/* Number of 32 byte buffers -- each buffer is 2 ms */ +#define BUFFER_SIZE 32 + +static char *tdesc = "Intercom using /dev/dsp for output"; + +static char *app = "Intercom"; + +STANDARD_LOCAL_USER; + +LOCAL_USER_DECL; + +static pthread_mutex_t sound_lock = PTHREAD_MUTEX_INITIALIZER; +static int sound = -1; + +static int write_audio(short *data, int len) +{ + int res; + struct audio_buf_info info; + pthread_mutex_lock(&sound_lock); + if (sound < 0) { + ast_log(LOG_WARNING, "Sound device closed?\n"); + pthread_mutex_unlock(&sound_lock); + return -1; + } + if (ioctl(sound, SNDCTL_DSP_GETOSPACE, &info)) { + ast_log(LOG_WARNING, "Unable to read output space\n"); + pthread_mutex_unlock(&sound_lock); + return -1; + } + res = write(sound, data, len); + pthread_mutex_unlock(&sound_lock); + return res; +} + +static int create_audio() +{ + int fmt, desired, res, fd; + fd = open(DEV_DSP, O_WRONLY); + if (fd < 0) { + ast_log(LOG_WARNING, "Unable to open %s: %s\n", DEV_DSP, strerror(errno)); + close(fd); + return -1; + } + fmt = AFMT_S16_LE; + res = ioctl(fd, SNDCTL_DSP_SETFMT, &fmt); + if (res < 0) { + ast_log(LOG_WARNING, "Unable to set format to 16-bit signed\n"); + close(fd); + return -1; + } + fmt = 0; + res = ioctl(fd, SNDCTL_DSP_STEREO, &fmt); + if (res < 0) { + ast_log(LOG_WARNING, "Failed to set audio device to mono\n"); + close(fd); + return -1; + } + /* 8000 Hz desired */ + desired = 8000; + fmt = desired; + res = ioctl(fd, SNDCTL_DSP_SPEED, &fmt); + if (res < 0) { + ast_log(LOG_WARNING, "Failed to set audio device to mono\n"); + close(fd); + return -1; + } + if (fmt != desired) { + ast_log(LOG_WARNING, "Requested %d Hz, got %d Hz -- sound may be choppy\n"); + } +#if 1 + /* 2 bytes * 15 units of 2^5 = 32 bytes per buffer */ + fmt = ((BUFFER_SIZE) << 16) | (0x0005); + res = ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &fmt); + if (res < 0) { + ast_log(LOG_WARNING, "Unable to set fragment size -- sound may be choppy\n"); + } +#endif + sound = fd; + return 0; +} + +static int intercom_exec(struct ast_channel *chan, void *data) +{ + int res = 0; + struct localuser *u; + struct ast_frame *f; + struct ast_channel *trans; + if (!data) { + ast_log(LOG_WARNING, "Playback requires an argument (filename)\n"); + return -1; + } + LOCAL_USER_ADD(u); + /* See if we need a translator */ + if (!(chan->format & AST_FORMAT_SLINEAR)) + trans = ast_translator_create(chan, AST_FORMAT_SLINEAR, AST_DIRECTION_IN); + else + trans = chan; + if (trans) { + /* Read packets from the channel */ + while(!res) { + res = ast_waitfor(trans, -1); + if (res > 0) { + res = 0; + f = ast_read(trans); + if (f) { + if (f->frametype == AST_FRAME_DTMF) { + ast_frfree(f); + break; + } else { + if (f->frametype == AST_FRAME_VOICE) { + if (f->subclass == AST_FORMAT_SLINEAR) { + res = write_audio(f->data, f->datalen); + if (res > 0) + res = 0; + } else + ast_log(LOG_DEBUG, "Unable to handle non-signed linear frame (%d)\n", f->subclass); + } + } + ast_frfree(f); + } else + res = -1; + } + } + if (trans != chan) + ast_translator_destroy(trans); + } else + ast_log(LOG_WARNING, "Unable to build translator to signed linear format on '%s'\n", chan->name); + LOCAL_USER_REMOVE(u); + return res; +} + +int unload_module(void) +{ + STANDARD_HANGUP_LOCALUSERS; + if (sound > -1) + close(sound); + return ast_unregister_application(app); +} + +int load_module(void) +{ + if (create_audio()) + return -1; + return ast_register_application(app, intercom_exec); +} + +char *description(void) +{ + return tdesc; +} + +int usecount(void) +{ + int res; + STANDARD_USECOUNT(res); + return res; +} |