Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:47:48 2009

## Asterisk developer's documentation

# app_intercom.c

Go to the documentation of this file.

    00001 /*
    00002  * Asterisk -- An open source telephony toolkit.
    00003  *
    00004  * Copyright (C) 1999 - 2005, Digium, Inc.
    00005  *
    00006  * Mark Spencer <markster@digium.com>
    00007  *
    00008  * See http://www.asterisk.org for more information about
    00009  * the Asterisk project. Please do not directly contact
    00010  * any of the maintainers of this project for assistance;
    00011  * the project provides a web site, mailing lists and IRC
    00012  * channels for your use.
    00013  *
    00014  * This program is free software, distributed under the terms of
    00015  * the GNU General Public License Version 2. See the LICENSE file
    00016  * at the top of the source tree.
    00017  */
    00018
    00019 /*! \file
    00020  *
    00021  * \brief Use /dev/dsp as an intercom.
    00022  *
    00023  * \ingroup applications
    00024  */
    00025
    00026 #include <stdio.h>
    00027 #include <unistd.h>
    00028 #include <errno.h>
    00029 #include <sys/ioctl.h>
    00030 #include <string.h>
    00031 #include <stdlib.h>
    00032 #include <sys/time.h>
    00033 #include <netinet/in.h>
    00034
    00035 #if defined(__linux__)
    00036 #include <linux/soundcard.h>
    00037 #elif defined(__FreeBSD__)
    00038 #include <sys/soundcard.h>
    00039 #else
    00040 #include <soundcard.h>
    00041 #endif
    00042
    00043 #include "asterisk.h"
    00044
    00045 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 7221 $")
    00046
    00047 #include "asterisk/lock.h"
    00048 #include "asterisk/file.h"
    00049 #include "asterisk/frame.h"
    00050 #include "asterisk/logger.h"
    00051 #include "asterisk/channel.h"
    00052 #include "asterisk/pbx.h"
    00053 #include "asterisk/module.h"
    00054 #include "asterisk/translate.h"
    00055
    00056 #ifdef __OpenBSD__
    00057 #define DEV_DSP "/dev/audio"
    00058 #else
    00059 #define DEV_DSP "/dev/dsp"
    00060 #endif
    00061
    00062 /* Number of 32 byte buffers -- each buffer is 2 ms */
    00063 #define BUFFER_SIZE 32
    00064
    00065 static char *tdesc = "Intercom using /dev/dsp for output";
    00066
    00067 static char *app = "Intercom";
    00068
    00069 static char *synopsis = "(Obsolete) Send to Intercom";
    00070 static char *descrip =
    00071 "  Intercom(): Sends the user to the intercom (i.e. /dev/dsp).  This program\n"
    00072 "is generally considered  obselete by the chan_oss module.  User can terminate\n"with a DTMF tone, or by hangup.\n";
    00073
    00074 STANDARD_LOCAL_USER;
    00075
    00076 LOCAL_USER_DECL;
    00077
    00078 AST_MUTEX_DEFINE_STATIC(sound_lock);
    00079 static int sound = -1;
    00080
    00081 static int write_audio(short *data, int len)
    00082 {
    00083    int res;
    00084    struct audio_buf_info info;
    00085    ast_mutex_lock(&sound_lock);
    00086    if (sound < 0) {
    00087       ast_log(LOG_WARNING, "Sound device closed?\n");
    00088       ast_mutex_unlock(&sound_lock);
    00089       return -1;
    00090    }
    00091     if (ioctl(sound, SNDCTL_DSP_GETOSPACE, &info)) {
    00092       ast_log(LOG_WARNING, "Unable to read output space\n");
    00093       ast_mutex_unlock(&sound_lock);
    00094         return -1;
    00095     }
    00096    res = write(sound, data, len);
    00097    ast_mutex_unlock(&sound_lock);
    00098    return res;
    00099 }
    00100
    00101 static int create_audio(void)
    00102 {
    00103    int fmt, desired, res, fd;
    00104    fd = open(DEV_DSP, O_WRONLY);
    00105    if (fd < 0) {
    00106       ast_log(LOG_WARNING, "Unable to open %s: %s\n", DEV_DSP, strerror(errno));
    00107       close(fd);
    00108       return -1;
    00109    }
    00110    fmt = AFMT_S16_LE;
    00111    res = ioctl(fd, SNDCTL_DSP_SETFMT, &fmt);
    00112    if (res < 0) {
    00113       ast_log(LOG_WARNING, "Unable to set format to 16-bit signed\n");
    00114       close(fd);
    00115       return -1;
    00116    }
    00117    fmt = 0;
    00118    res = ioctl(fd, SNDCTL_DSP_STEREO, &fmt);
    00119    if (res < 0) {
    00120       ast_log(LOG_WARNING, "Failed to set audio device to mono\n");
    00121       close(fd);
    00122       return -1;
    00123    }
    00124    /* 8000 Hz desired */
    00125    desired = 8000;
    00126    fmt = desired;
    00127    res = ioctl(fd, SNDCTL_DSP_SPEED, &fmt);
    00128    if (res < 0) {
    00129       ast_log(LOG_WARNING, "Failed to set audio device to mono\n");
    00130       close(fd);
    00131       return -1;
    00132    }
    00133    if (fmt != desired) {
    00134       ast_log(LOG_WARNING, "Requested %d Hz, got %d Hz -- sound may be choppy\n", desired, fmt);
    00135    }
    00136 #if 1
    00137    /* 2 bytes * 15 units of 2^5 = 32 bytes per buffer */
    00138    fmt = ((BUFFER_SIZE) << 16) | (0x0005);
    00139    res = ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &fmt);
    00140    if (res < 0) {
    00141       ast_log(LOG_WARNING, "Unable to set fragment size -- sound may be choppy\n");
    00142    }
    00143 #endif
    00144    sound = fd;
    00145    return 0;
    00146 }
    00147
    00148 static int intercom_exec(struct ast_channel *chan, void *data)
    00149 {
    00150    int res = 0;
    00151    struct localuser *u;
    00152    struct ast_frame *f;
    00153    int oreadformat;
    00154    LOCAL_USER_ADD(u);
    00155    /* Remember original read format */
    00156    oreadformat = chan->readformat;
    00157    /* Set mode to signed linear */
    00158    res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
    00159    if (res < 0) {
    00160       ast_log(LOG_WARNING, "Unable to set format to signed linear on channel %s\n", chan->name);
    00161       LOCAL_USER_REMOVE(u);
    00162       return -1;
    00163    }
    00164    /* Read packets from the channel */
    00165    while(!res) {
    00166       res = ast_waitfor(chan, -1);
    00167       if (res > 0) {
    00168          res = 0;
    00169          f = ast_read(chan);
    00170          if (f) {
    00171             if (f->frametype == AST_FRAME_DTMF) {
    00172                ast_frfree(f);
    00173                break;
    00174             } else {
    00175                if (f->frametype == AST_FRAME_VOICE) {
    00176                   if (f->subclass == AST_FORMAT_SLINEAR) {
    00177                      res = write_audio(f->data, f->datalen);
    00178                      if (res > 0)
    00179                         res = 0;
    00180                   } else
    00181                      ast_log(LOG_DEBUG, "Unable to handle non-signed linear frame (%d)\n", f->subclass);
    00182                }
    00183             }
    00184             ast_frfree(f);
    00185          } else
    00186             res = -1;
    00187       }
    00188    }
    00189
    00190    if (!res)
    00191       ast_set_read_format(chan, oreadformat);
    00192
    00193    LOCAL_USER_REMOVE(u);
    00194
    00195    return res;
    00196 }
    00197
    00198 int unload_module(void)
    00199 {
    00200    int res;
    00201
    00202    if (sound > -1)
    00203       close(sound);
    00204
    00205    res = ast_unregister_application(app);
    00206
    00207    STANDARD_HANGUP_LOCALUSERS;
    00208
    00209    return res;
    00210 }
    00211
    00212 int load_module(void)
    00213 {
    00214    if (create_audio())
    00215       return -1;
    00216    return ast_register_application(app, intercom_exec, synopsis, descrip);
    00217 }
    00218
    00219 char *description(void)
    00220 {
    00221    return tdesc;
    00222 }
    00223
    00224 int usecount(void)
    00225 {
    00226    int res;
    00227    STANDARD_USECOUNT(res);
    00228    return res;
    00229 }
    00230
    00231 char *key()
    00232 {
    00233    return ASTERISK_GPL_KEY;
    00234 }