Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:47:48 2009

## Asterisk developer's documentation

# app_nbscat.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 Silly application to play an NBScat file -- uses nbscat8k
    00022  *
    00023  * \ingroup applications
    00024  */
    00025
    00026 #include <string.h>
    00027 #include <stdio.h>
    00028 #include <signal.h>
    00029 #include <stdlib.h>
    00030 #include <unistd.h>
    00031 #include <fcntl.h>
    00032 #include <sys/time.h>
    00033 #include <sys/socket.h>
    00034
    00035 #include "asterisk.h"
    00036
    00037 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 48374 $")
    00038
    00039 #include "asterisk/lock.h"
    00040 #include "asterisk/file.h"
    00041 #include "asterisk/logger.h"
    00042 #include "asterisk/channel.h"
    00043 #include "asterisk/frame.h"
    00044 #include "asterisk/pbx.h"
    00045 #include "asterisk/module.h"
    00046 #include "asterisk/translate.h"
    00047 #include "asterisk/options.h"
    00048
    00049 #define LOCAL_NBSCAT "/usr/local/bin/nbscat8k"
    00050 #define NBSCAT "/usr/bin/nbscat8k"
    00051
    00052 #ifndef AF_LOCAL
    00053 #define AF_LOCAL AF_UNIX
    00054 #endif
    00055
    00056 static char *tdesc = "Silly NBS Stream Application";
    00057
    00058 static char *app = "NBScat";
    00059
    00060 static char *synopsis = "Play an NBS local stream";
    00061
    00062 static char *descrip =
    00063 "  NBScat: Executes nbscat to listen to the local NBS stream.\n"
    00064 "User can exit by pressing any key\n.";
    00065
    00066 STANDARD_LOCAL_USER;
    00067
    00068 LOCAL_USER_DECL;
    00069
    00070 static int NBScatplay(int fd)
    00071 {
    00072    int res;
    00073    int x;
    00074    sigset_t fullset, oldset;
    00075
    00076    sigfillset(&fullset);
    00077    pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
    00078
    00079    res = fork();
    00080    if (res < 0)
    00081       ast_log(LOG_WARNING, "Fork failed\n");
    00082    if (res) {
    00083       pthread_sigmask(SIG_SETMASK, &oldset, NULL);
    00084       return res;
    00085    }
    00086    signal(SIGPIPE, SIG_DFL);
    00087    pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
    00088
    00089    if (option_highpriority)
    00090       ast_set_priority(0);
    00091
    00092    dup2(fd, STDOUT_FILENO);
    00093    for (x = STDERR_FILENO + 1; x < 1024; x++) {
    00094       if (x != STDOUT_FILENO)
    00095          close(x);
    00096    }
    00097    /* Most commonly installed in /usr/local/bin */
    00098    execl(NBSCAT, "nbscat8k", "-d", (char *)NULL);
    00099    execl(LOCAL_NBSCAT, "nbscat8k", "-d", (char *)NULL);
    00100    ast_log(LOG_WARNING, "Execute of nbscat8k failed\n");
    00101    _exit(0);
    00102 }
    00103
    00104 static int timed_read(int fd, void *data, int datalen)
    00105 {
    00106    int res;
    00107    struct pollfd fds[1];
    00108    fds[0].fd = fd;
    00109    fds[0].events = POLLIN;
    00110    res = poll(fds, 1, 2000);
    00111    if (res < 1) {
    00112       ast_log(LOG_NOTICE, "Selected timed out/errored out with %d\n", res);
    00113       return -1;
    00114    }
    00115    return read(fd, data, datalen);
    00116
    00117 }
    00118
    00119 static int NBScat_exec(struct ast_channel *chan, void *data)
    00120 {
    00121    int res=0;
    00122    struct localuser *u;
    00123    int fds[2];
    00124    int ms = -1;
    00125    int pid = -1;
    00126    int owriteformat;
    00127    struct timeval next;
    00128    struct ast_frame *f;
    00129    struct myframe {
    00130       struct ast_frame f;
    00131       char offset[AST_FRIENDLY_OFFSET];
    00132       short frdata[160];
    00133    } myf;
    00134
    00135    LOCAL_USER_ADD(u);
    00136
    00137    if (socketpair(AF_LOCAL, SOCK_STREAM, 0, fds)) {
    00138       ast_log(LOG_WARNING, "Unable to create socketpair\n");
    00139       LOCAL_USER_REMOVE(u);
    00140       return -1;
    00141    }
    00142
    00143    ast_stopstream(chan);
    00144
    00145    owriteformat = chan->writeformat;
    00146    res = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
    00147    if (res < 0) {
    00148       ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
    00149       LOCAL_USER_REMOVE(u);
    00150       return -1;
    00151    }
    00152
    00153    res = NBScatplay(fds[1]);
    00154    /* Wait 1000 ms first */
    00155    next = ast_tvnow();
    00156    next.tv_sec += 1;
    00157    if (res >= 0) {
    00158       pid = res;
    00159       /* Order is important -- there's almost always going to be mp3...  we want to prioritize the
    00160          user */
    00161       for (;;) {
    00162          ms = ast_tvdiff_ms(next, ast_tvnow());
    00163          if (ms <= 0) {
    00164             res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata));
    00165             if (res > 0) {
    00166                myf.f.frametype = AST_FRAME_VOICE;
    00167                myf.f.subclass = AST_FORMAT_SLINEAR;
    00168                myf.f.datalen = res;
    00169                myf.f.samples = res / 2;
    00170                myf.f.mallocd = 0;
    00171                myf.f.offset = AST_FRIENDLY_OFFSET;
    00172                myf.f.src = __PRETTY_FUNCTION__;
    00173                myf.f.delivery.tv_sec = 0;
    00174                myf.f.delivery.tv_usec = 0;
    00175                myf.f.data = myf.frdata;
    00176                if (ast_write(chan, &myf.f) < 0) {
    00177                   res = -1;
    00178                   break;
    00179                }
    00180             } else {
    00181                ast_log(LOG_DEBUG, "No more mp3\n");
    00182                res = 0;
    00183                break;
    00184             }
    00185             next = ast_tvadd(next, ast_samp2tv(myf.f.samples, 8000));
    00186          } else {
    00187             ms = ast_waitfor(chan, ms);
    00188             if (ms < 0) {
    00189                ast_log(LOG_DEBUG, "Hangup detected\n");
    00190                res = -1;
    00191                break;
    00192             }
    00193             if (ms) {
    00194                f = ast_read(chan);
    00195                if (!f) {
    00196                   ast_log(LOG_DEBUG, "Null frame == hangup() detected\n");
    00197                   res = -1;
    00198                   break;
    00199                }
    00200                if (f->frametype == AST_FRAME_DTMF) {
    00201                   ast_log(LOG_DEBUG, "User pressed a key\n");
    00202                   ast_frfree(f);
    00203                   res = 0;
    00204                   break;
    00205                }
    00206                ast_frfree(f);
    00207             }
    00208          }
    00209       }
    00210    }
    00211    close(fds[0]);
    00212    close(fds[1]);
    00213
    00214    if (pid > -1)
    00215       kill(pid, SIGKILL);
    00216    if (!res && owriteformat)
    00217       ast_set_write_format(chan, owriteformat);
    00218
    00219    LOCAL_USER_REMOVE(u);
    00220
    00221    return res;
    00222 }
    00223
    00224 int unload_module(void)
    00225 {
    00226    int res;
    00227
    00228    res = ast_unregister_application(app);
    00229
    00230    STANDARD_HANGUP_LOCALUSERS;
    00231
    00232    return res;
    00233 }
    00234
    00235 int load_module(void)
    00236 {
    00237    return ast_register_application(app, NBScat_exec, synopsis, descrip);
    00238 }
    00239
    00240 char *description(void)
    00241 {
    00242    return tdesc;
    00243 }
    00244
    00245 int usecount(void)
    00246 {
    00247    int res;
    00248    STANDARD_USECOUNT(res);
    00249    return res;
    00250 }
    00251
    00252 char *key()
    00253 {
    00254    return ASTERISK_GPL_KEY;
    00255 }