#include "asterisk.h"
#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/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"
Go to the source code of this file.
Data Structures | |
struct | nbs_pvt |
Functions | |
AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"Network Broadcast Sound Support") | |
static int | load_module (void) |
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) |
static int | unload_module (void) |
Variables | |
static char | context [AST_MAX_EXTENSION] = "default" |
static struct ast_channel_tech | nbs_tech |
static int | prefformat = AST_FORMAT_SLINEAR |
static const char | tdesc [] = "Network Broadcast Sound Driver" |
static char | type [] = "NBS" |
Definition in file chan_nbs.c.
AST_MODULE_INFO_STANDARD | ( | ASTERISK_GPL_KEY | , | |
"Network Broadcast Sound Support" | ||||
) |
static int load_module | ( | void | ) | [static] |
Definition at line 292 of file chan_nbs.c.
References ast_channel_register(), ast_log(), and LOG_ERROR.
00293 { 00294 /* Make sure we can register our channel type */ 00295 if (ast_channel_register(&nbs_tech)) { 00296 ast_log(LOG_ERROR, "Unable to register channel class %s\n", type); 00297 return -1; 00298 } 00299 return 0; 00300 }
static struct nbs_pvt* nbs_alloc | ( | void * | data | ) | [static, read] |
Definition at line 128 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().
00129 { 00130 struct nbs_pvt *p; 00131 int flags = 0; 00132 char stream[256]; 00133 char *opts; 00134 00135 ast_copy_string(stream, data, sizeof(stream)); 00136 if ((opts = strchr(stream, ':'))) { 00137 *opts = '\0'; 00138 opts++; 00139 } else 00140 opts = ""; 00141 p = malloc(sizeof(struct nbs_pvt)); 00142 if (p) { 00143 memset(p, 0, sizeof(struct nbs_pvt)); 00144 if (!ast_strlen_zero(opts)) { 00145 if (strchr(opts, 'm')) 00146 flags |= NBS_FLAG_MUTE; 00147 if (strchr(opts, 'o')) 00148 flags |= NBS_FLAG_OVERSPEAK; 00149 if (strchr(opts, 'e')) 00150 flags |= NBS_FLAG_EMERGENCY; 00151 if (strchr(opts, 'O')) 00152 flags |= NBS_FLAG_OVERRIDE; 00153 } else 00154 flags = NBS_FLAG_OVERSPEAK; 00155 00156 ast_copy_string(p->stream, stream, sizeof(p->stream)); 00157 p->nbs = nbs_newstream("asterisk", stream, flags); 00158 if (!p->nbs) { 00159 ast_log(LOG_WARNING, "Unable to allocate new NBS stream '%s' with flags %d\n", stream, flags); 00160 free(p); 00161 p = NULL; 00162 } else { 00163 /* Set for 8000 hz mono, 640 samples */ 00164 nbs_setbitrate(p->nbs, 8000); 00165 nbs_setchannels(p->nbs, 1); 00166 nbs_setblocksize(p->nbs, 640); 00167 nbs_setblocking(p->nbs, 0); 00168 } 00169 } 00170 return p; 00171 }
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, 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 ast_module_user_remove, free, nbs_pvt::nbs, and nbs_pvt::u.
Referenced by nbs_hangup(), and nbs_request().
00121 { 00122 if (p->nbs) 00123 nbs_delstream(p->nbs); 00124 ast_module_user_remove(p->u); 00125 free(p); 00126 }
static int nbs_hangup | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 173 of file chan_nbs.c.
References ast_log(), ast_setstate(), AST_STATE_DOWN, LOG_DEBUG, LOG_WARNING, nbs_destroy(), option_debug, and ast_channel::tech_pvt.
00174 { 00175 struct nbs_pvt *p; 00176 p = ast->tech_pvt; 00177 if (option_debug) 00178 ast_log(LOG_DEBUG, "nbs_hangup(%s)\n", ast->name); 00179 if (!ast->tech_pvt) { 00180 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n"); 00181 return 0; 00182 } 00183 nbs_destroy(p); 00184 ast->tech_pvt = NULL; 00185 ast_setstate(ast, AST_STATE_DOWN); 00186 return 0; 00187 }
static struct ast_channel* nbs_new | ( | struct nbs_pvt * | i, | |
int | state | |||
) | [static, read] |
Definition at line 232 of file chan_nbs.c.
References ast_channel_alloc(), ast_hangup(), ast_log(), ast_module_user_add, ast_pbx_start(), AST_STATE_DOWN, AST_STATE_RING, ast_string_field_set, ast_channel::context, ast_channel::exten, ast_channel::fds, language, LOG_WARNING, 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, nbs_pvt::u, and ast_channel::writeformat.
Referenced by nbs_request().
00233 { 00234 struct ast_channel *tmp; 00235 tmp = ast_channel_alloc(1, state, 0, 0, "", "s", context, 0, "NBS/%s", i->stream); 00236 if (tmp) { 00237 tmp->tech = &nbs_tech; 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 if (state == AST_STATE_RING) 00245 tmp->rings = 1; 00246 tmp->tech_pvt = i; 00247 ast_copy_string(tmp->context, context, sizeof(tmp->context)); 00248 ast_copy_string(tmp->exten, "s", sizeof(tmp->exten)); 00249 ast_string_field_set(tmp, language, ""); 00250 i->owner = tmp; 00251 i->u = ast_module_user_add(tmp); 00252 if (state != AST_STATE_DOWN) { 00253 if (ast_pbx_start(tmp)) { 00254 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 00255 ast_hangup(tmp); 00256 } 00257 } 00258 } else 00259 ast_log(LOG_WARNING, "Unable to allocate channel structure\n"); 00260 return tmp; 00261 }
static struct ast_channel * nbs_request | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int * | cause | |||
) | [static, read] |
Definition at line 264 of file chan_nbs.c.
References AST_FORMAT_SLINEAR, ast_log(), AST_STATE_DOWN, LOG_NOTICE, nbs_alloc(), nbs_destroy(), and nbs_new().
00265 { 00266 int oldformat; 00267 struct nbs_pvt *p; 00268 struct ast_channel *tmp = NULL; 00269 00270 oldformat = format; 00271 format &= (AST_FORMAT_SLINEAR); 00272 if (!format) { 00273 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", oldformat); 00274 return NULL; 00275 } 00276 p = nbs_alloc(data); 00277 if (p) { 00278 tmp = nbs_new(p, AST_STATE_DOWN); 00279 if (!tmp) 00280 nbs_destroy(p); 00281 } 00282 return tmp; 00283 }
static struct ast_frame * nbs_xread | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 189 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_frame::offset, ast_frame::samples, ast_frame::src, and ast_channel::tech_pvt.
00190 { 00191 struct nbs_pvt *p = ast->tech_pvt; 00192 00193 00194 /* Some nice norms */ 00195 p->fr.datalen = 0; 00196 p->fr.samples = 0; 00197 p->fr.data = NULL; 00198 p->fr.src = type; 00199 p->fr.offset = 0; 00200 p->fr.mallocd=0; 00201 p->fr.delivery.tv_sec = 0; 00202 p->fr.delivery.tv_usec = 0; 00203 00204 ast_log(LOG_DEBUG, "Returning null frame on %s\n", ast->name); 00205 00206 return &p->fr; 00207 }
static int nbs_xwrite | ( | struct ast_channel * | ast, | |
struct ast_frame * | frame | |||
) | [static] |
Definition at line 209 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.
00210 { 00211 struct nbs_pvt *p = ast->tech_pvt; 00212 /* Write a frame of (presumably voice) data */ 00213 if (frame->frametype != AST_FRAME_VOICE) { 00214 if (frame->frametype != AST_FRAME_IMAGE) 00215 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype); 00216 return 0; 00217 } 00218 if (!(frame->subclass & 00219 (AST_FORMAT_SLINEAR))) { 00220 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass); 00221 return 0; 00222 } 00223 if (ast->_state != AST_STATE_UP) { 00224 /* Don't try tos end audio on-hook */ 00225 return 0; 00226 } 00227 if (nbs_write(p->nbs, frame->data, frame->datalen / 2) < 0) 00228 return -1; 00229 return 0; 00230 }
static int unload_module | ( | void | ) | [static] |
Definition at line 285 of file chan_nbs.c.
References ast_channel_unregister().
00286 { 00287 /* First, take us out of the channel loop */ 00288 ast_channel_unregister(&nbs_tech); 00289 return 0; 00290 }
char context[AST_MAX_EXTENSION] = "default" [static] |
Definition at line 62 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 57 of file chan_nbs.c.
char type[] = "NBS" [static] |
Definition at line 63 of file chan_nbs.c.