Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:48:33 2009

## Asterisk developer's documentation

# chan_nbs.c File Reference

Network broadcast sound support channel driver. More...

`#include <stdio.h>`
`#include <string.h>`
`#include <sys/socket.h>`
`#include <sys/time.h>`
`#include <errno.h>`
`#include <unistd.h>`
`#include <stdlib.h>`
`#include <arpa/inet.h>`
`#include <fcntl.h>`
`#include <sys/ioctl.h>`
`#include <nbs.h>`
`#include "asterisk.h"`
`#include "asterisk/lock.h"`
`#include "asterisk/channel.h"`
`#include "asterisk/config.h"`
`#include "asterisk/logger.h"`
`#include "asterisk/module.h"`
`#include "asterisk/pbx.h"`
`#include "asterisk/options.h"`
`#include "asterisk/utils.h"`

Include dependency graph for chan_nbs.c:

Go to the source code of this file.

## Data Structures

struct | nbs_pvt

## Functions

static int | __unload_module (void)
| AST_MUTEX_DEFINE_STATIC (usecnt_lock)
char * | description ()
| Provides a description of the module.
char * | key ()
| Returns the ASTERISK_GPL_KEY.
int | load_module ()
| Initialize the module.
static struct nbs_pvt * | nbs_alloc (void *data)
static int | nbs_call (struct ast_channel *ast, char *dest, int timeout)
static void | nbs_destroy (struct nbs_pvt *p)
static int | nbs_hangup (struct ast_channel *ast)
static struct ast_channel * | nbs_new (struct nbs_pvt *i, int state)
static struct ast_channel * | nbs_request (const char *type, int format, void *data, int *cause)
static struct ast_frame * | nbs_xread (struct ast_channel *ast)
static int | nbs_xwrite (struct ast_channel *ast, struct ast_frame *frame)
int | unload_module (void)
| Cleanup all module structures, sockets, etc.
int | usecount ()
| Provides a usecount.

## Variables

static char | context [AST_MAX_EXTENSION] = "default"
static const char | desc [] = "Network Broadcast Sound Support"
static struct ast_channel_tech | nbs_tech
static int | prefformat = AST_FORMAT_SLINEAR
static const char | tdesc [] = "Network Broadcast Sound Driver"
static const char | type [] = "NBS"
static int | usecnt = 0

## Detailed Description

Network broadcast sound support channel driver.

Author:
  Mark Spencer <markster@digium.com>

Definition in file chan_nbs.c.

## Function Documentation

static int __unload_module | ( | void |  | ) | `[static]`

Definition at line 289 of file chan_nbs.c.

References ast_channel_unregister().

    00290 {
    00291    /* First, take us out of the channel loop */
    00292    ast_channel_unregister(&nbs_tech);
    00293    return 0;
    00294 }

AST_MUTEX_DEFINE_STATIC | ( | usecnt_lock |  | ) |

char* description | ( | void |  | ) |

Provides a description of the module.

Returns:
  a short description of your module

Definition at line 317 of file chan_nbs.c.

    00318 {
    00319    return (char *) desc;
    00320 }

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 322 of file chan_nbs.c.

References ASTERISK_GPL_KEY.

    00323 {
    00324    return ASTERISK_GPL_KEY;
    00325 }

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 301 of file chan_nbs.c.

References __unload_module(), ast_channel_register(), ast_log(), and LOG_ERROR.

    00302 {
    00303    /* Make sure we can register our channel type */
    00304    if (ast_channel_register(&nbs_tech)) {
    00305       ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
    00306       __unload_module();
    00307       return -1;
    00308    }
    00309    return 0;
    00310 }

static struct nbs_pvt* nbs_alloc | ( | void * | data | ) | `[static, read]`

Definition at line 127 of file chan_nbs.c.

References ast_log(), ast_strlen_zero(), free, LOG_WARNING, malloc, nbs_pvt::nbs, and nbs_pvt::stream.

Referenced by nbs_request().

    00128 {
    00129    struct nbs_pvt *p;
    00130    int flags = 0;
    00131    char stream[256] = "";
    00132    char *opts;
    00133    strncpy(stream, data, sizeof(stream) - 1);
    00134    if ((opts = strchr(stream, ':'))) {
    00135       *opts = '\0';
    00136       opts++;
    00137    } else
    00138       opts = "";
    00139    p = malloc(sizeof(struct nbs_pvt));
    00140    if (p) {
    00141       memset(p, 0, sizeof(struct nbs_pvt));
    00142       if (!ast_strlen_zero(opts)) {
    00143          if (strchr(opts, 'm'))
    00144             flags |= NBS_FLAG_MUTE;
    00145          if (strchr(opts, 'o'))
    00146             flags |= NBS_FLAG_OVERSPEAK;
    00147          if (strchr(opts, 'e'))
    00148             flags |= NBS_FLAG_EMERGENCY;
    00149          if (strchr(opts, 'O'))
    00150             flags |= NBS_FLAG_OVERRIDE;
    00151       } else
    00152          flags = NBS_FLAG_OVERSPEAK;
    00153
    00154       strncpy(p->stream, stream, sizeof(p->stream) - 1);
    00155       p->nbs = nbs_newstream("asterisk", stream, flags);
    00156       if (!p->nbs) {
    00157          ast_log(LOG_WARNING, "Unable to allocate new NBS stream '%s' with flags %d\n", stream, flags);
    00158          free(p);
    00159          p = NULL;
    00160       } else {
    00161          /* Set for 8000 hz mono, 640 samples */
    00162          nbs_setbitrate(p->nbs, 8000);
    00163          nbs_setchannels(p->nbs, 1);
    00164          nbs_setblocksize(p->nbs, 640);
    00165          nbs_setblocking(p->nbs, 0);
    00166       }
    00167    }
    00168    return p;
    00169 }

static int nbs_call | ( | struct ast_channel * | ast,
|  | char * | dest,
|  | int | timeout |
| ) |  |  | `[static]`

Definition at line 93 of file chan_nbs.c.

References ast_channel::_state, AST_CONTROL_ANSWER, AST_CONTROL_CONGESTION, ast_log(), ast_queue_control(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, LOG_DEBUG, LOG_WARNING, ast_channel::name, nbs_pvt::nbs, option_debug, and ast_channel::tech_pvt.

    00094 {
    00095    struct nbs_pvt *p;
    00096
    00097    p = ast->tech_pvt;
    00098
    00099    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
    00100       ast_log(LOG_WARNING, "nbs_call called on %s, neither down nor reserved\n", ast->name);
    00101       return -1;
    00102    }
    00103    /* When we call, it just works, really, there's no destination...  Just
    00104       ring the phone and wait for someone to answer */
    00105    if (option_debug)
    00106       ast_log(LOG_DEBUG, "Calling %s on %s\n", dest, ast->name);
    00107
    00108    /* If we can't connect, return congestion */
    00109    if (nbs_connect(p->nbs)) {
    00110       ast_log(LOG_WARNING, "NBS Connection failed on %s\n", ast->name);
    00111       ast_queue_control(ast, AST_CONTROL_CONGESTION);
    00112    } else {
    00113       ast_setstate(ast, AST_STATE_RINGING);
    00114       ast_queue_control(ast, AST_CONTROL_ANSWER);
    00115    }
    00116
    00117    return 0;
    00118 }

static void nbs_destroy | ( | struct nbs_pvt * | p | ) | `[static]`

Definition at line 120 of file chan_nbs.c.

References free, and nbs_pvt::nbs.

Referenced by nbs_hangup(), and nbs_request().

    00121 {
    00122    if (p->nbs)
    00123       nbs_delstream(p->nbs);
    00124    free(p);
    00125 }

static int nbs_hangup | ( | struct ast_channel * | ast | ) | `[static]`

Definition at line 171 of file chan_nbs.c.

References ast_log(), ast_setstate(), AST_STATE_DOWN, LOG_DEBUG, LOG_WARNING, ast_channel::name, nbs_destroy(), option_debug, and ast_channel::tech_pvt.

    00172 {
    00173    struct nbs_pvt *p;
    00174    p = ast->tech_pvt;
    00175    if (option_debug)
    00176       ast_log(LOG_DEBUG, "nbs_hangup(%s)\n", ast->name);
    00177    if (!ast->tech_pvt) {
    00178       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
    00179       return 0;
    00180    }
    00181    nbs_destroy(p);
    00182    ast->tech_pvt = NULL;
    00183    ast_setstate(ast, AST_STATE_DOWN);
    00184    return 0;
    00185 }

static struct ast_channel* nbs_new | ( | struct nbs_pvt * | i,
|  | int | state |
| ) |  |  | `[static, read]`

Definition at line 230 of file chan_nbs.c.

References ast_channel_alloc(), ast_hangup(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pbx_start(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RING, ast_update_use_count(), ast_channel::context, ast_channel::exten, ast_channel::fds, ast_channel::language, LOG_WARNING, ast_channel::name, ast_channel::nativeformats, nbs_pvt::nbs, nbs_pvt::owner, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, ast_channel::rings, nbs_pvt::stream, ast_channel::tech, ast_channel::tech_pvt, ast_channel::type, usecnt_lock, and ast_channel::writeformat.

Referenced by nbs_request().

    00231 {
    00232    struct ast_channel *tmp;
    00233    tmp = ast_channel_alloc(1);
    00234    if (tmp) {
    00235       tmp->tech = &nbs_tech;
    00236       snprintf(tmp->name, sizeof(tmp->name), "NBS/%s", i->stream);
    00237       tmp->type = type;
    00238       tmp->fds[0] = nbs_fd(i->nbs);
    00239       tmp->nativeformats = prefformat;
    00240       tmp->rawreadformat = prefformat;
    00241       tmp->rawwriteformat = prefformat;
    00242       tmp->writeformat = prefformat;
    00243       tmp->readformat = prefformat;
    00244       ast_setstate(tmp, state);
    00245       if (state == AST_STATE_RING)
    00246          tmp->rings = 1;
    00247       tmp->tech_pvt = i;
    00248       strncpy(tmp->context, context, sizeof(tmp->context)-1);
    00249       strncpy(tmp->exten, "s",  sizeof(tmp->exten) - 1);
    00250       tmp->language[0] = '\0';
    00251       i->owner = tmp;
    00252       ast_mutex_lock(&usecnt_lock);
    00253       usecnt++;
    00254       ast_mutex_unlock(&usecnt_lock);
    00255       ast_update_use_count();
    00256       if (state != AST_STATE_DOWN) {
    00257          if (ast_pbx_start(tmp)) {
    00258             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
    00259             ast_hangup(tmp);
    00260          }
    00261       }
    00262    } else
    00263       ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
    00264    return tmp;
    00265 }

static struct ast_channel * nbs_request | ( | const char * | type,
|  | int | format,
|  | void * | data,
|  | int * | cause |
| ) |  |  | `[static, read]`

Definition at line 268 of file chan_nbs.c.

References AST_FORMAT_SLINEAR, ast_log(), AST_STATE_DOWN, LOG_NOTICE, nbs_alloc(), nbs_destroy(), and nbs_new().

    00269 {
    00270    int oldformat;
    00271    struct nbs_pvt *p;
    00272    struct ast_channel *tmp = NULL;
    00273
    00274    oldformat = format;
    00275    format &= (AST_FORMAT_SLINEAR);
    00276    if (!format) {
    00277       ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", oldformat);
    00278       return NULL;
    00279    }
    00280    p = nbs_alloc(data);
    00281    if (p) {
    00282       tmp = nbs_new(p, AST_STATE_DOWN);
    00283       if (!tmp)
    00284          nbs_destroy(p);
    00285    }
    00286    return tmp;
    00287 }

static struct ast_frame * nbs_xread | ( | struct ast_channel * | ast | ) | `[static, read]`

Definition at line 187 of file chan_nbs.c.

References ast_log(), ast_frame::data, ast_frame::datalen, ast_frame::delivery, nbs_pvt::fr, LOG_DEBUG, ast_frame::mallocd, ast_channel::name, ast_frame::offset, ast_frame::samples, ast_frame::src, and ast_channel::tech_pvt.

    00188 {
    00189    struct nbs_pvt *p = ast->tech_pvt;
    00190
    00191
    00192    /* Some nice norms */
    00193    p->fr.datalen = 0;
    00194    p->fr.samples = 0;
    00195    p->fr.data =  NULL;
    00196    p->fr.src = type;
    00197    p->fr.offset = 0;
    00198    p->fr.mallocd=0;
    00199    p->fr.delivery.tv_sec = 0;
    00200    p->fr.delivery.tv_usec = 0;
    00201
    00202    ast_log(LOG_DEBUG, "Returning null frame on %s\n", ast->name);
    00203
    00204    return &p->fr;
    00205 }

static int nbs_xwrite | ( | struct ast_channel * | ast,
|  | struct ast_frame * | frame |
| ) |  |  | `[static]`

Definition at line 207 of file chan_nbs.c.

References ast_channel::_state, AST_FORMAT_SLINEAR, AST_FRAME_IMAGE, AST_FRAME_VOICE, ast_log(), AST_STATE_UP, ast_frame::data, ast_frame::datalen, ast_frame::frametype, LOG_WARNING, nbs_pvt::nbs, ast_frame::subclass, and ast_channel::tech_pvt.

    00208 {
    00209    struct nbs_pvt *p = ast->tech_pvt;
    00210    /* Write a frame of (presumably voice) data */
    00211    if (frame->frametype != AST_FRAME_VOICE) {
    00212       if (frame->frametype != AST_FRAME_IMAGE)
    00213          ast_log(LOG_WARNING, "Don't know what to do with  frame type '%d'\n", frame->frametype);
    00214       return 0;
    00215    }
    00216    if (!(frame->subclass &
    00217       (AST_FORMAT_SLINEAR))) {
    00218       ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
    00219       return 0;
    00220    }
    00221    if (ast->_state != AST_STATE_UP) {
    00222       /* Don't try tos end audio on-hook */
    00223       return 0;
    00224    }
    00225    if (nbs_write(p->nbs, frame->data, frame->datalen / 2) < 0)
    00226       return -1;
    00227    return 0;
    00228 }

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 296 of file chan_nbs.c.

References __unload_module().

    00297 {
    00298    return __unload_module();
    00299 }

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 312 of file chan_nbs.c.

    00313 {
    00314    return usecnt;
    00315 }

## Variable Documentation

char context[AST_MAX_EXTENSION] = "default"`[static]`

Definition at line 64 of file chan_nbs.c.

const char desc[] = "Network Broadcast Sound Support"`[static]`

Definition at line 53 of file chan_nbs.c.

struct ast_channel_tech nbs_tech`[static]`

Definition at line 82 of file chan_nbs.c.

int prefformat = AST_FORMAT_SLINEAR`[static]`

Definition at line 60 of file chan_nbs.c.

const char tdesc[] = "Network Broadcast Sound Driver"`[static]`

Definition at line 55 of file chan_nbs.c.

const char type[] = "NBS"`[static]`

Definition at line 54 of file chan_nbs.c.

int usecnt = 0`[static]`

Definition at line 57 of file chan_nbs.c.