00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "asterisk.h"
00033
00034 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 60989 $")
00035
00036 #include <stdio.h>
00037 #include <string.h>
00038 #include <sys/socket.h>
00039 #include <sys/time.h>
00040 #include <errno.h>
00041 #include <unistd.h>
00042 #include <stdlib.h>
00043 #include <arpa/inet.h>
00044 #include <fcntl.h>
00045 #include <sys/ioctl.h>
00046 #include <nbs.h>
00047
00048 #include "asterisk/lock.h"
00049 #include "asterisk/channel.h"
00050 #include "asterisk/config.h"
00051 #include "asterisk/logger.h"
00052 #include "asterisk/module.h"
00053 #include "asterisk/pbx.h"
00054 #include "asterisk/options.h"
00055 #include "asterisk/utils.h"
00056
00057 static const char tdesc[] = "Network Broadcast Sound Driver";
00058
00059
00060 static int prefformat = AST_FORMAT_SLINEAR;
00061
00062 static char context[AST_MAX_EXTENSION] = "default";
00063 static char type[] = "NBS";
00064
00065
00066
00067 struct nbs_pvt {
00068 NBS *nbs;
00069 struct ast_channel *owner;
00070 char app[16];
00071 char stream[80];
00072 struct ast_frame fr;
00073 struct ast_module_user *u;
00074 };
00075
00076 static struct ast_channel *nbs_request(const char *type, int format, void *data, int *cause);
00077 static int nbs_call(struct ast_channel *ast, char *dest, int timeout);
00078 static int nbs_hangup(struct ast_channel *ast);
00079 static struct ast_frame *nbs_xread(struct ast_channel *ast);
00080 static int nbs_xwrite(struct ast_channel *ast, struct ast_frame *frame);
00081
00082 static const struct ast_channel_tech nbs_tech = {
00083 .type = type,
00084 .description = tdesc,
00085 .capabilities = AST_FORMAT_SLINEAR,
00086 .requester = nbs_request,
00087 .call = nbs_call,
00088 .hangup = nbs_hangup,
00089 .read = nbs_xread,
00090 .write = nbs_xwrite,
00091 };
00092
00093 static int nbs_call(struct ast_channel *ast, char *dest, int timeout)
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
00104
00105 if (option_debug)
00106 ast_log(LOG_DEBUG, "Calling %s on %s\n", dest, ast->name);
00107
00108
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 }
00119
00120 static void nbs_destroy(struct nbs_pvt *p)
00121 {
00122 if (p->nbs)
00123 nbs_delstream(p->nbs);
00124 ast_module_user_remove(p->u);
00125 free(p);
00126 }
00127
00128 static struct nbs_pvt *nbs_alloc(void *data)
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
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 }
00172
00173 static int nbs_hangup(struct ast_channel *ast)
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 }
00188
00189 static struct ast_frame *nbs_xread(struct ast_channel *ast)
00190 {
00191 struct nbs_pvt *p = ast->tech_pvt;
00192
00193
00194
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 }
00208
00209 static int nbs_xwrite(struct ast_channel *ast, struct ast_frame *frame)
00210 {
00211 struct nbs_pvt *p = ast->tech_pvt;
00212
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
00225 return 0;
00226 }
00227 if (nbs_write(p->nbs, frame->data, frame->datalen / 2) < 0)
00228 return -1;
00229 return 0;
00230 }
00231
00232 static struct ast_channel *nbs_new(struct nbs_pvt *i, int state)
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 }
00262
00263
00264 static struct ast_channel *nbs_request(const char *type, int format, void *data, int *cause)
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 }
00284
00285 static int unload_module(void)
00286 {
00287
00288 ast_channel_unregister(&nbs_tech);
00289 return 0;
00290 }
00291
00292 static int load_module(void)
00293 {
00294
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 }
00301
00302 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Network Broadcast Sound Support");