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: 356573 $")
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 struct ast_format prefformat;
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, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause);
00071 static int nbs_call(struct ast_channel *ast, const 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 struct ast_channel_tech nbs_tech = {
00077 .type = type,
00078 .description = tdesc,
00079 .requester = nbs_request,
00080 .call = nbs_call,
00081 .hangup = nbs_hangup,
00082 .read = nbs_xread,
00083 .write = nbs_xwrite,
00084 };
00085
00086 static int nbs_call(struct ast_channel *ast, const char *dest, int timeout)
00087 {
00088 struct nbs_pvt *p;
00089
00090 p = ast_channel_tech_pvt(ast);
00091
00092 if ((ast_channel_state(ast) != AST_STATE_DOWN) && (ast_channel_state(ast) != AST_STATE_RESERVED)) {
00093 ast_log(LOG_WARNING, "nbs_call called on %s, neither down nor reserved\n", ast_channel_name(ast));
00094 return -1;
00095 }
00096
00097
00098 ast_debug(1, "Calling %s on %s\n", dest, ast_channel_name(ast));
00099
00100
00101 if (nbs_connect(p->nbs)) {
00102 ast_log(LOG_WARNING, "NBS Connection failed on %s\n", ast_channel_name(ast));
00103 ast_queue_control(ast, AST_CONTROL_CONGESTION);
00104 } else {
00105 ast_setstate(ast, AST_STATE_RINGING);
00106 ast_queue_control(ast, AST_CONTROL_ANSWER);
00107 }
00108
00109 return 0;
00110 }
00111
00112 static void nbs_destroy(struct nbs_pvt *p)
00113 {
00114 if (p->nbs)
00115 nbs_delstream(p->nbs);
00116 ast_module_user_remove(p->u);
00117 ast_free(p);
00118 }
00119
00120 static struct nbs_pvt *nbs_alloc(const char *data)
00121 {
00122 struct nbs_pvt *p;
00123 int flags = 0;
00124 char stream[256];
00125 char *opts;
00126
00127 ast_copy_string(stream, data, sizeof(stream));
00128 if ((opts = strchr(stream, ':'))) {
00129 *opts = '\0';
00130 opts++;
00131 } else
00132 opts = "";
00133 p = ast_calloc(1, sizeof(*p));
00134 if (p) {
00135 if (!ast_strlen_zero(opts)) {
00136 if (strchr(opts, 'm'))
00137 flags |= NBS_FLAG_MUTE;
00138 if (strchr(opts, 'o'))
00139 flags |= NBS_FLAG_OVERSPEAK;
00140 if (strchr(opts, 'e'))
00141 flags |= NBS_FLAG_EMERGENCY;
00142 if (strchr(opts, 'O'))
00143 flags |= NBS_FLAG_OVERRIDE;
00144 } else
00145 flags = NBS_FLAG_OVERSPEAK;
00146
00147 ast_copy_string(p->stream, stream, sizeof(p->stream));
00148 p->nbs = nbs_newstream("asterisk", stream, flags);
00149 if (!p->nbs) {
00150 ast_log(LOG_WARNING, "Unable to allocate new NBS stream '%s' with flags %d\n", stream, flags);
00151 ast_free(p);
00152 p = NULL;
00153 } else {
00154
00155 nbs_setbitrate(p->nbs, 8000);
00156 nbs_setchannels(p->nbs, 1);
00157 nbs_setblocksize(p->nbs, 640);
00158 nbs_setblocking(p->nbs, 0);
00159 }
00160 }
00161 return p;
00162 }
00163
00164 static int nbs_hangup(struct ast_channel *ast)
00165 {
00166 struct nbs_pvt *p;
00167 p = ast_channel_tech_pvt(ast);
00168 ast_debug(1, "nbs_hangup(%s)\n", ast_channel_name(ast));
00169 if (!ast_channel_tech_pvt(ast)) {
00170 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
00171 return 0;
00172 }
00173 nbs_destroy(p);
00174 ast_channel_tech_pvt_set(ast, NULL);
00175 ast_setstate(ast, AST_STATE_DOWN);
00176 return 0;
00177 }
00178
00179 static struct ast_frame *nbs_xread(struct ast_channel *ast)
00180 {
00181 struct nbs_pvt *p = ast_channel_tech_pvt(ast);
00182
00183
00184
00185 p->fr.datalen = 0;
00186 p->fr.samples = 0;
00187 p->fr.data.ptr = NULL;
00188 p->fr.src = type;
00189 p->fr.offset = 0;
00190 p->fr.mallocd=0;
00191 p->fr.delivery.tv_sec = 0;
00192 p->fr.delivery.tv_usec = 0;
00193
00194 ast_debug(1, "Returning null frame on %s\n", ast_channel_name(ast));
00195
00196 return &p->fr;
00197 }
00198
00199 static int nbs_xwrite(struct ast_channel *ast, struct ast_frame *frame)
00200 {
00201 struct nbs_pvt *p = ast_channel_tech_pvt(ast);
00202
00203 if (frame->frametype != AST_FRAME_VOICE) {
00204 if (frame->frametype != AST_FRAME_IMAGE)
00205 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
00206 return 0;
00207 }
00208 if (frame->subclass.format.id != (AST_FORMAT_SLINEAR)) {
00209 ast_log(LOG_WARNING, "Cannot handle frames in %s format\n", ast_getformatname(&frame->subclass.format));
00210 return 0;
00211 }
00212 if (ast_channel_state(ast) != AST_STATE_UP) {
00213
00214 return 0;
00215 }
00216 if (nbs_write(p->nbs, frame->data.ptr, frame->datalen / 2) < 0)
00217 return -1;
00218 return 0;
00219 }
00220
00221 static struct ast_channel *nbs_new(struct nbs_pvt *i, int state, const char *linkedid)
00222 {
00223 struct ast_channel *tmp;
00224 tmp = ast_channel_alloc(1, state, 0, 0, "", "s", context, linkedid, 0, "NBS/%s", i->stream);
00225 if (tmp) {
00226 ast_channel_tech_set(tmp, &nbs_tech);
00227 ast_channel_set_fd(tmp, 0, nbs_fd(i->nbs));
00228
00229 ast_format_cap_add(ast_channel_nativeformats(tmp), &prefformat);
00230 ast_format_copy(ast_channel_rawreadformat(tmp), &prefformat);
00231 ast_format_copy(ast_channel_rawwriteformat(tmp), &prefformat);
00232 ast_format_copy(ast_channel_writeformat(tmp), &prefformat);
00233 ast_format_copy(ast_channel_readformat(tmp), &prefformat);
00234 if (state == AST_STATE_RING)
00235 ast_channel_rings_set(tmp, 1);
00236 ast_channel_tech_pvt_set(tmp, i);
00237 ast_channel_context_set(tmp, context);
00238 ast_channel_exten_set(tmp, "s");
00239 ast_channel_language_set(tmp, "");
00240 i->owner = tmp;
00241 i->u = ast_module_user_add(tmp);
00242 if (state != AST_STATE_DOWN) {
00243 if (ast_pbx_start(tmp)) {
00244 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
00245 ast_hangup(tmp);
00246 }
00247 }
00248 } else
00249 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
00250 return tmp;
00251 }
00252
00253
00254 static struct ast_channel *nbs_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause)
00255 {
00256 struct nbs_pvt *p;
00257 struct ast_channel *tmp = NULL;
00258
00259 if (!(ast_format_cap_iscompatible(cap, &prefformat))) {
00260 char tmp[256];
00261 ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), cap));
00262 return NULL;
00263 }
00264 p = nbs_alloc(data);
00265 if (p) {
00266 tmp = nbs_new(p, AST_STATE_DOWN, requestor ? ast_channel_linkedid(requestor) : NULL);
00267 if (!tmp)
00268 nbs_destroy(p);
00269 }
00270 return tmp;
00271 }
00272
00273 static int unload_module(void)
00274 {
00275
00276 ast_channel_unregister(&nbs_tech);
00277 nbs_tech.capabilities = ast_format_cap_destroy(nbs_tech.capabilities);
00278 return 0;
00279 }
00280
00281 static int load_module(void)
00282 {
00283 ast_format_set(&prefformat, AST_FORMAT_SLINEAR, 0);
00284 if (!(nbs_tech.capabilities = ast_format_cap_alloc())) {
00285 return AST_MODULE_LOAD_FAILURE;
00286 }
00287 ast_format_cap_add(nbs_tech.capabilities, &prefformat);
00288
00289 if (ast_channel_register(&nbs_tech)) {
00290 ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
00291 return AST_MODULE_LOAD_DECLINE;
00292 }
00293 return AST_MODULE_LOAD_SUCCESS;
00294 }
00295
00296 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Network Broadcast Sound Support");