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
00033 #include "asterisk.h"
00034
00035 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 328209 $")
00036
00037 #include <sys/socket.h>
00038 #include <sys/time.h>
00039 #include <arpa/inet.h>
00040 #include <fcntl.h>
00041 #include <sys/ioctl.h>
00042 #include <nbs.h>
00043
00044 #include "asterisk/lock.h"
00045 #include "asterisk/channel.h"
00046 #include "asterisk/config.h"
00047 #include "asterisk/module.h"
00048 #include "asterisk/pbx.h"
00049 #include "asterisk/utils.h"
00050
00051 static const char tdesc[] = "Network Broadcast Sound Driver";
00052
00053
00054 static format_t prefformat = AST_FORMAT_SLINEAR;
00055
00056 static char context[AST_MAX_EXTENSION] = "default";
00057 static const char type[] = "NBS";
00058
00059
00060
00061 struct nbs_pvt {
00062 NBS *nbs;
00063 struct ast_channel *owner;
00064 char app[16];
00065 char stream[80];
00066 struct ast_frame fr;
00067 struct ast_module_user *u;
00068 };
00069
00070 static struct ast_channel *nbs_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
00071 static int nbs_call(struct ast_channel *ast, char *dest, int timeout);
00072 static int nbs_hangup(struct ast_channel *ast);
00073 static struct ast_frame *nbs_xread(struct ast_channel *ast);
00074 static int nbs_xwrite(struct ast_channel *ast, struct ast_frame *frame);
00075
00076 static const struct ast_channel_tech nbs_tech = {
00077 .type = type,
00078 .description = tdesc,
00079 .capabilities = AST_FORMAT_SLINEAR,
00080 .requester = nbs_request,
00081 .call = nbs_call,
00082 .hangup = nbs_hangup,
00083 .read = nbs_xread,
00084 .write = nbs_xwrite,
00085 };
00086
00087 static int nbs_call(struct ast_channel *ast, char *dest, int timeout)
00088 {
00089 struct nbs_pvt *p;
00090
00091 p = ast->tech_pvt;
00092
00093 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
00094 ast_log(LOG_WARNING, "nbs_call called on %s, neither down nor reserved\n", ast->name);
00095 return -1;
00096 }
00097
00098
00099 ast_debug(1, "Calling %s on %s\n", dest, ast->name);
00100
00101
00102 if (nbs_connect(p->nbs)) {
00103 ast_log(LOG_WARNING, "NBS Connection failed on %s\n", ast->name);
00104 ast_queue_control(ast, AST_CONTROL_CONGESTION);
00105 } else {
00106 ast_setstate(ast, AST_STATE_RINGING);
00107 ast_queue_control(ast, AST_CONTROL_ANSWER);
00108 }
00109
00110 return 0;
00111 }
00112
00113 static void nbs_destroy(struct nbs_pvt *p)
00114 {
00115 if (p->nbs)
00116 nbs_delstream(p->nbs);
00117 ast_module_user_remove(p->u);
00118 ast_free(p);
00119 }
00120
00121 static struct nbs_pvt *nbs_alloc(void *data)
00122 {
00123 struct nbs_pvt *p;
00124 int flags = 0;
00125 char stream[256];
00126 char *opts;
00127
00128 ast_copy_string(stream, data, sizeof(stream));
00129 if ((opts = strchr(stream, ':'))) {
00130 *opts = '\0';
00131 opts++;
00132 } else
00133 opts = "";
00134 p = ast_calloc(1, sizeof(*p));
00135 if (p) {
00136 if (!ast_strlen_zero(opts)) {
00137 if (strchr(opts, 'm'))
00138 flags |= NBS_FLAG_MUTE;
00139 if (strchr(opts, 'o'))
00140 flags |= NBS_FLAG_OVERSPEAK;
00141 if (strchr(opts, 'e'))
00142 flags |= NBS_FLAG_EMERGENCY;
00143 if (strchr(opts, 'O'))
00144 flags |= NBS_FLAG_OVERRIDE;
00145 } else
00146 flags = NBS_FLAG_OVERSPEAK;
00147
00148 ast_copy_string(p->stream, stream, sizeof(p->stream));
00149 p->nbs = nbs_newstream("asterisk", stream, flags);
00150 if (!p->nbs) {
00151 ast_log(LOG_WARNING, "Unable to allocate new NBS stream '%s' with flags %d\n", stream, flags);
00152 ast_free(p);
00153 p = NULL;
00154 } else {
00155
00156 nbs_setbitrate(p->nbs, 8000);
00157 nbs_setchannels(p->nbs, 1);
00158 nbs_setblocksize(p->nbs, 640);
00159 nbs_setblocking(p->nbs, 0);
00160 }
00161 }
00162 return p;
00163 }
00164
00165 static int nbs_hangup(struct ast_channel *ast)
00166 {
00167 struct nbs_pvt *p;
00168 p = ast->tech_pvt;
00169 ast_debug(1, "nbs_hangup(%s)\n", ast->name);
00170 if (!ast->tech_pvt) {
00171 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
00172 return 0;
00173 }
00174 nbs_destroy(p);
00175 ast->tech_pvt = NULL;
00176 ast_setstate(ast, AST_STATE_DOWN);
00177 return 0;
00178 }
00179
00180 static struct ast_frame *nbs_xread(struct ast_channel *ast)
00181 {
00182 struct nbs_pvt *p = ast->tech_pvt;
00183
00184
00185
00186 p->fr.datalen = 0;
00187 p->fr.samples = 0;
00188 p->fr.data.ptr = NULL;
00189 p->fr.src = type;
00190 p->fr.offset = 0;
00191 p->fr.mallocd=0;
00192 p->fr.delivery.tv_sec = 0;
00193 p->fr.delivery.tv_usec = 0;
00194
00195 ast_debug(1, "Returning null frame on %s\n", ast->name);
00196
00197 return &p->fr;
00198 }
00199
00200 static int nbs_xwrite(struct ast_channel *ast, struct ast_frame *frame)
00201 {
00202 struct nbs_pvt *p = ast->tech_pvt;
00203
00204 if (frame->frametype != AST_FRAME_VOICE) {
00205 if (frame->frametype != AST_FRAME_IMAGE)
00206 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
00207 return 0;
00208 }
00209 if (!(frame->subclass.codec &
00210 (AST_FORMAT_SLINEAR))) {
00211 ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(frame->subclass.codec));
00212 return 0;
00213 }
00214 if (ast->_state != AST_STATE_UP) {
00215
00216 return 0;
00217 }
00218 if (nbs_write(p->nbs, frame->data.ptr, frame->datalen / 2) < 0)
00219 return -1;
00220 return 0;
00221 }
00222
00223 static struct ast_channel *nbs_new(struct nbs_pvt *i, int state, const char *linkedid)
00224 {
00225 struct ast_channel *tmp;
00226 tmp = ast_channel_alloc(1, state, 0, 0, "", "s", context, linkedid, 0, "NBS/%s", i->stream);
00227 if (tmp) {
00228 tmp->tech = &nbs_tech;
00229 ast_channel_set_fd(tmp, 0, nbs_fd(i->nbs));
00230 tmp->nativeformats = prefformat;
00231 tmp->rawreadformat = prefformat;
00232 tmp->rawwriteformat = prefformat;
00233 tmp->writeformat = prefformat;
00234 tmp->readformat = prefformat;
00235 if (state == AST_STATE_RING)
00236 tmp->rings = 1;
00237 tmp->tech_pvt = i;
00238 ast_copy_string(tmp->context, context, sizeof(tmp->context));
00239 ast_copy_string(tmp->exten, "s", sizeof(tmp->exten));
00240 ast_string_field_set(tmp, language, "");
00241 i->owner = tmp;
00242 i->u = ast_module_user_add(tmp);
00243 if (state != AST_STATE_DOWN) {
00244 if (ast_pbx_start(tmp)) {
00245 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
00246 ast_hangup(tmp);
00247 }
00248 }
00249 } else
00250 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
00251 return tmp;
00252 }
00253
00254
00255 static struct ast_channel *nbs_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
00256 {
00257 format_t oldformat;
00258 struct nbs_pvt *p;
00259 struct ast_channel *tmp = NULL;
00260
00261 oldformat = format;
00262 format &= (AST_FORMAT_SLINEAR);
00263 if (!format) {
00264 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname(oldformat));
00265 return NULL;
00266 }
00267 p = nbs_alloc(data);
00268 if (p) {
00269 tmp = nbs_new(p, AST_STATE_DOWN, requestor ? requestor->linkedid : NULL);
00270 if (!tmp)
00271 nbs_destroy(p);
00272 }
00273 return tmp;
00274 }
00275
00276 static int unload_module(void)
00277 {
00278
00279 ast_channel_unregister(&nbs_tech);
00280 return 0;
00281 }
00282
00283 static int load_module(void)
00284 {
00285
00286 if (ast_channel_register(&nbs_tech)) {
00287 ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
00288 return -1;
00289 }
00290 return 0;
00291 }
00292
00293 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Network Broadcast Sound Support");