Thu Oct 11 06:47:03 2012

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  * \author Mark Spencer <markster@digium.com>
00024  *  
00025  * \ingroup applications
00026  */
00027  
00028 #include "asterisk.h"
00029 
00030 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 182947 $")
00031 
00032 #include <fcntl.h>
00033 #include <sys/time.h>
00034 #include <sys/socket.h>
00035 #include <signal.h>
00036 
00037 #include "asterisk/lock.h"
00038 #include "asterisk/file.h"
00039 #include "asterisk/channel.h"
00040 #include "asterisk/frame.h"
00041 #include "asterisk/pbx.h"
00042 #include "asterisk/module.h"
00043 #include "asterisk/translate.h"
00044 #include "asterisk/app.h"
00045 
00046 /*** DOCUMENTATION
00047    <application name="NBScat" language="en_US">
00048       <synopsis>
00049          Play an NBS local stream.
00050       </synopsis>
00051       <syntax />
00052       <description>
00053          <para>Executes nbscat to listen to the local NBS stream.
00054          User can exit by pressing any key.</para>
00055       </description>
00056    </application>
00057  ***/
00058 
00059 #define LOCAL_NBSCAT "/usr/local/bin/nbscat8k"
00060 #define NBSCAT "/usr/bin/nbscat8k"
00061 
00062 #ifndef AF_LOCAL
00063 #define AF_LOCAL AF_UNIX
00064 #endif
00065 
00066 static char *app = "NBScat";
00067 
00068 static int NBScatplay(int fd)
00069 {
00070    int res;
00071 
00072    res = ast_safe_fork(0);
00073    if (res < 0) {
00074       ast_log(LOG_WARNING, "Fork failed\n");
00075    }
00076 
00077    if (res) {
00078       return res;
00079    }
00080 
00081    if (ast_opt_high_priority)
00082       ast_set_priority(0);
00083 
00084    dup2(fd, STDOUT_FILENO);
00085    ast_close_fds_above_n(STDERR_FILENO);
00086    /* Most commonly installed in /usr/local/bin */
00087    execl(NBSCAT, "nbscat8k", "-d", (char *)NULL);
00088    execl(LOCAL_NBSCAT, "nbscat8k", "-d", (char *)NULL);
00089    fprintf(stderr, "Execute of nbscat8k failed\n");
00090    _exit(0);
00091 }
00092 
00093 static int timed_read(int fd, void *data, int datalen)
00094 {
00095    int res;
00096    struct pollfd fds[1];
00097    fds[0].fd = fd;
00098    fds[0].events = POLLIN;
00099    res = ast_poll(fds, 1, 2000);
00100    if (res < 1) {
00101       ast_log(LOG_NOTICE, "Selected timed out/errored out with %d\n", res);
00102       return -1;
00103    }
00104    return read(fd, data, datalen);
00105    
00106 }
00107 
00108 static int NBScat_exec(struct ast_channel *chan, void *data)
00109 {
00110    int res=0;
00111    int fds[2];
00112    int ms = -1;
00113    int pid = -1;
00114    int owriteformat;
00115    struct timeval next;
00116    struct ast_frame *f;
00117    struct myframe {
00118       struct ast_frame f;
00119       char offset[AST_FRIENDLY_OFFSET];
00120       short frdata[160];
00121    } myf;
00122    
00123    if (socketpair(AF_LOCAL, SOCK_STREAM, 0, fds)) {
00124       ast_log(LOG_WARNING, "Unable to create socketpair\n");
00125       return -1;
00126    }
00127    
00128    ast_stopstream(chan);
00129 
00130    owriteformat = chan->writeformat;
00131    res = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
00132    if (res < 0) {
00133       ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
00134       return -1;
00135    }
00136    
00137    res = NBScatplay(fds[1]);
00138    /* Wait 1000 ms first */
00139    next = ast_tvnow();
00140    next.tv_sec += 1;
00141    if (res >= 0) {
00142       pid = res;
00143       /* Order is important -- there's almost always going to be mp3...  we want to prioritize the
00144          user */
00145       for (;;) {
00146          ms = ast_tvdiff_ms(next, ast_tvnow());
00147          if (ms <= 0) {
00148             res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata));
00149             if (res > 0) {
00150                myf.f.frametype = AST_FRAME_VOICE;
00151                myf.f.subclass = AST_FORMAT_SLINEAR;
00152                myf.f.datalen = res;
00153                myf.f.samples = res / 2;
00154                myf.f.mallocd = 0;
00155                myf.f.offset = AST_FRIENDLY_OFFSET;
00156                myf.f.src = __PRETTY_FUNCTION__;
00157                myf.f.delivery.tv_sec = 0;
00158                myf.f.delivery.tv_usec = 0;
00159                myf.f.data.ptr = myf.frdata;
00160                if (ast_write(chan, &myf.f) < 0) {
00161                   res = -1;
00162                   break;
00163                }
00164             } else {
00165                ast_debug(1, "No more mp3\n");
00166                res = 0;
00167                break;
00168             }
00169             next = ast_tvadd(next, ast_samp2tv(myf.f.samples, 8000));
00170          } else {
00171             ms = ast_waitfor(chan, ms);
00172             if (ms < 0) {
00173                ast_debug(1, "Hangup detected\n");
00174                res = -1;
00175                break;
00176             }
00177             if (ms) {
00178                f = ast_read(chan);
00179                if (!f) {
00180                   ast_debug(1, "Null frame == hangup() detected\n");
00181                   res = -1;
00182                   break;
00183                }
00184                if (f->frametype == AST_FRAME_DTMF) {
00185                   ast_debug(1, "User pressed a key\n");
00186                   ast_frfree(f);
00187                   res = 0;
00188                   break;
00189                }
00190                ast_frfree(f);
00191             } 
00192          }
00193       }
00194    }
00195    close(fds[0]);
00196    close(fds[1]);
00197    
00198    if (pid > -1)
00199       kill(pid, SIGKILL);
00200    if (!res && owriteformat)
00201       ast_set_write_format(chan, owriteformat);
00202 
00203    return res;
00204 }
00205 
00206 static int unload_module(void)
00207 {
00208    return ast_unregister_application(app);
00209 }
00210 
00211 static int load_module(void)
00212 {
00213    return ast_register_application_xml(app, NBScat_exec);
00214 }
00215 
00216 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Silly NBS Stream Application");

Generated on Thu Oct 11 06:47:03 2012 for Asterisk - the Open Source PBX by  doxygen 1.5.6