Mon Sep 18 09:13:42 2006

Asterisk developer's documentation


app_nbscat.c File Reference

Silly application to play an NBScat file -- uses nbscat8k. More...

#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/socket.h>
#include "asterisk.h"
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/frame.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/options.h"

Go to the source code of this file.

Defines

#define AF_LOCAL   AF_UNIX
#define LOCAL_NBSCAT   "/usr/local/bin/nbscat8k"
#define NBSCAT   "/usr/bin/nbscat8k"

Functions

char * description (void)
 Provides a description of the module.
char * key ()
 Returns the ASTERISK_GPL_KEY.
int load_module (void)
 Initialize the module.
static int NBScat_exec (struct ast_channel *chan, void *data)
static int NBScatplay (int fd)
static int timed_read (int fd, void *data, int datalen)
int unload_module (void)
 Cleanup all module structures, sockets, etc.
int usecount (void)
 Provides a usecount.

Variables

static char * app = "NBScat"
static char * descrip
 LOCAL_USER_DECL
 STANDARD_LOCAL_USER
static char * synopsis = "Play an NBS local stream"
static char * tdesc = "Silly NBS Stream Application"


Detailed Description

Silly application to play an NBScat file -- uses nbscat8k.

Definition in file app_nbscat.c.


Define Documentation

#define AF_LOCAL   AF_UNIX

Definition at line 53 of file app_nbscat.c.

#define LOCAL_NBSCAT   "/usr/local/bin/nbscat8k"

Definition at line 49 of file app_nbscat.c.

Referenced by NBScatplay().

#define NBSCAT   "/usr/bin/nbscat8k"

Definition at line 50 of file app_nbscat.c.

Referenced by NBScatplay().


Function Documentation

char* description ( void   ) 

Provides a description of the module.

Returns:
a short description of your module

Definition at line 230 of file app_nbscat.c.

00231 {
00232    return tdesc;
00233 }

char* key ( void   ) 

Returns the ASTERISK_GPL_KEY.

This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:

 char *key(void) {
         return ASTERISK_GPL_KEY;
 }

Returns:
ASTERISK_GPL_KEY

Definition at line 242 of file app_nbscat.c.

References ASTERISK_GPL_KEY.

00243 {
00244    return ASTERISK_GPL_KEY;
00245 }

int load_module ( void   ) 

Initialize the module.

Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.

Returns:
int Always 0.

Definition at line 225 of file app_nbscat.c.

References ast_register_application(), and NBScat_exec().

00226 {
00227    return ast_register_application(app, NBScat_exec, synopsis, descrip);
00228 }

static int NBScat_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 109 of file app_nbscat.c.

References AF_LOCAL, AST_FORMAT_SLINEAR, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frfree(), AST_FRIENDLY_OFFSET, ast_log(), ast_read(), ast_set_write_format(), ast_stopstream(), ast_tvadd(), ast_waitfor(), ast_write(), ast_frame::frametype, LOCAL_USER_ADD, LOCAL_USER_REMOVE, LOG_DEBUG, LOG_WARNING, NBScatplay(), offset, timed_read(), and ast_channel::writeformat.

Referenced by load_module().

00110 {
00111    int res=0;
00112    struct localuser *u;
00113    int fds[2];
00114    int ms = -1;
00115    int pid = -1;
00116    int owriteformat;
00117    struct timeval next;
00118    struct ast_frame *f;
00119    struct myframe {
00120       struct ast_frame f;
00121       char offset[AST_FRIENDLY_OFFSET];
00122       short frdata[160];
00123    } myf;
00124    
00125    LOCAL_USER_ADD(u);
00126 
00127    if (socketpair(AF_LOCAL, SOCK_STREAM, 0, fds)) {
00128       ast_log(LOG_WARNING, "Unable to create socketpair\n");
00129       LOCAL_USER_REMOVE(u);
00130       return -1;
00131    }
00132    
00133    ast_stopstream(chan);
00134 
00135    owriteformat = chan->writeformat;
00136    res = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
00137    if (res < 0) {
00138       ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
00139       LOCAL_USER_REMOVE(u);
00140       return -1;
00141    }
00142    
00143    res = NBScatplay(fds[1]);
00144    /* Wait 1000 ms first */
00145    next = ast_tvnow();
00146    next.tv_sec += 1;
00147    if (res >= 0) {
00148       pid = res;
00149       /* Order is important -- there's almost always going to be mp3...  we want to prioritize the
00150          user */
00151       for (;;) {
00152          ms = ast_tvdiff_ms(next, ast_tvnow());
00153          if (ms <= 0) {
00154             res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata));
00155             if (res > 0) {
00156                myf.f.frametype = AST_FRAME_VOICE;
00157                myf.f.subclass = AST_FORMAT_SLINEAR;
00158                myf.f.datalen = res;
00159                myf.f.samples = res / 2;
00160                myf.f.mallocd = 0;
00161                myf.f.offset = AST_FRIENDLY_OFFSET;
00162                myf.f.src = __PRETTY_FUNCTION__;
00163                myf.f.delivery.tv_sec = 0;
00164                myf.f.delivery.tv_usec = 0;
00165                myf.f.data = myf.frdata;
00166                if (ast_write(chan, &myf.f) < 0) {
00167                   res = -1;
00168                   break;
00169                }
00170             } else {
00171                ast_log(LOG_DEBUG, "No more mp3\n");
00172                res = 0;
00173                break;
00174             }
00175             next = ast_tvadd(next, ast_samp2tv(myf.f.samples, 8000));
00176          } else {
00177             ms = ast_waitfor(chan, ms);
00178             if (ms < 0) {
00179                ast_log(LOG_DEBUG, "Hangup detected\n");
00180                res = -1;
00181                break;
00182             }
00183             if (ms) {
00184                f = ast_read(chan);
00185                if (!f) {
00186                   ast_log(LOG_DEBUG, "Null frame == hangup() detected\n");
00187                   res = -1;
00188                   break;
00189                }
00190                if (f->frametype == AST_FRAME_DTMF) {
00191                   ast_log(LOG_DEBUG, "User pressed a key\n");
00192                   ast_frfree(f);
00193                   res = 0;
00194                   break;
00195                }
00196                ast_frfree(f);
00197             } 
00198          }
00199       }
00200    }
00201    close(fds[0]);
00202    close(fds[1]);
00203    
00204    if (pid > -1)
00205       kill(pid, SIGKILL);
00206    if (!res && owriteformat)
00207       ast_set_write_format(chan, owriteformat);
00208 
00209    LOCAL_USER_REMOVE(u);
00210 
00211    return res;
00212 }

static int NBScatplay ( int  fd  )  [static]

Definition at line 70 of file app_nbscat.c.

References ast_log(), ast_set_priority(), LOCAL_NBSCAT, LOG_WARNING, NBSCAT, and option_highpriority.

Referenced by NBScat_exec().

00071 {
00072    int res;
00073    int x;
00074    res = fork();
00075    if (res < 0) 
00076       ast_log(LOG_WARNING, "Fork failed\n");
00077    if (res)
00078       return res;
00079    if (option_highpriority)
00080       ast_set_priority(0);
00081 
00082    dup2(fd, STDOUT_FILENO);
00083    for (x=0;x<256;x++) {
00084       if (x != STDOUT_FILENO)
00085          close(x);
00086    }
00087    /* Most commonly installed in /usr/local/bin */
00088    execl(NBSCAT, "nbscat8k", "-d", (char *)NULL);
00089    execl(LOCAL_NBSCAT, "nbscat8k", "-d", (char *)NULL);
00090    ast_log(LOG_WARNING, "Execute of nbscat8k failed\n");
00091    return -1;
00092 }

static int timed_read ( int  fd,
void *  data,
int  datalen 
) [static]

Definition at line 94 of file app_nbscat.c.

References ast_log(), pollfd::events, pollfd::fd, LOG_NOTICE, poll(), and POLLIN.

00095 {
00096    int res;
00097    struct pollfd fds[1];
00098    fds[0].fd = fd;
00099    fds[0].events = POLLIN;
00100    res = poll(fds, 1, 2000);
00101    if (res < 1) {
00102       ast_log(LOG_NOTICE, "Selected timed out/errored out with %d\n", res);
00103       return -1;
00104    }
00105    return read(fd, data, datalen);
00106    
00107 }

int unload_module ( void   ) 

Cleanup all module structures, sockets, etc.

This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).

Returns:
Zero on success, or non-zero on error.

Definition at line 214 of file app_nbscat.c.

References ast_unregister_application(), and STANDARD_HANGUP_LOCALUSERS.

00215 {
00216    int res;
00217 
00218    res = ast_unregister_application(app);
00219 
00220    STANDARD_HANGUP_LOCALUSERS;
00221 
00222    return res;
00223 }

int usecount ( void   ) 

Provides a usecount.

This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.

Returns:
The module's usecount.

Definition at line 235 of file app_nbscat.c.

References STANDARD_USECOUNT.

00236 {
00237    int res;
00238    STANDARD_USECOUNT(res);
00239    return res;
00240 }


Variable Documentation

char* app = "NBScat" [static]

Definition at line 58 of file app_nbscat.c.

char* descrip [static]

Initial value:

 
"  NBScat: Executes nbscat to listen to the local NBS stream.\n"
"User can exit by pressing any key\n."

Definition at line 62 of file app_nbscat.c.

LOCAL_USER_DECL

Definition at line 68 of file app_nbscat.c.

STANDARD_LOCAL_USER

Definition at line 66 of file app_nbscat.c.

char* synopsis = "Play an NBS local stream" [static]

Definition at line 60 of file app_nbscat.c.

char* tdesc = "Silly NBS Stream Application" [static]

Definition at line 56 of file app_nbscat.c.


Generated on Mon Sep 18 09:13:42 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.7