Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:48:09 2009

## 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"`

Include dependency graph for app_nbscat.c:

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 240 of file app_nbscat.c.

    00241 {
    00242    return tdesc;
    00243 }

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 252 of file app_nbscat.c.

References ASTERISK_GPL_KEY.

    00253 {
    00254    return ASTERISK_GPL_KEY;
    00255 }

int load_module | ( | void |  | ) |

Initialize the module.

This function is called at module load time. Put all code in here that needs to set up your module's hardware, software, registrations, etc.

Returns:
  This function should return 0 on success and non-zero on failure. If the module is not loaded successfully, Asterisk will call its unload_module() function.

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.

TE STUFF END

Definition at line 235 of file app_nbscat.c.

References ast_register_application(), and NBScat_exec().

    00236 {
    00237    return ast_register_application(app, NBScat_exec, synopsis, descrip);
    00238 }

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

Definition at line 119 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().

    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 }

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    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 }

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

Definition at line 104 of file app_nbscat.c.

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

    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 }

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 224 of file app_nbscat.c.

References ast_unregister_application(), and STANDARD_HANGUP_LOCALUSERS.

    00225 {
    00226    int res;
    00227
    00228    res = ast_unregister_application(app);
    00229
    00230    STANDARD_HANGUP_LOCALUSERS;
    00231
    00232    return res;
    00233 }

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 245 of file app_nbscat.c.

References STANDARD_USECOUNT.

    00246 {
    00247    int res;
    00248    STANDARD_USECOUNT(res);
    00249    return res;
    00250 }

## 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.