chan_nbs.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. /*
  2. * Asterisk -- A telephony toolkit for Linux.
  3. *
  4. * Generic Linux Telephony Interface driver
  5. *
  6. * Copyright (C) 1999, Mark Spencer
  7. *
  8. * Mark Spencer <markster@linux-support.net>
  9. *
  10. * This program is free software, distributed under the terms of
  11. * the GNU General Public License
  12. */
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include <asterisk/lock.h>
  16. #include <asterisk/channel.h>
  17. #include <asterisk/channel_pvt.h>
  18. #include <asterisk/config.h>
  19. #include <asterisk/logger.h>
  20. #include <asterisk/module.h>
  21. #include <asterisk/pbx.h>
  22. #include <asterisk/options.h>
  23. #include <sys/socket.h>
  24. #include <sys/time.h>
  25. #include <errno.h>
  26. #include <unistd.h>
  27. #include <stdlib.h>
  28. #include <arpa/inet.h>
  29. #include <fcntl.h>
  30. #include <sys/ioctl.h>
  31. #include <nbs.h>
  32. static char *desc = "Network Broadcast Sound Support";
  33. static char *type = "NBS";
  34. static char *tdesc = "Network Broadcast Sound Driver";
  35. static int usecnt =0;
  36. /* Only linear is allowed */
  37. static int prefformat = AST_FORMAT_SLINEAR;
  38. AST_MUTEX_DEFINE_STATIC(usecnt_lock);
  39. static char context[AST_MAX_EXTENSION] = "default";
  40. /* NBS creates private structures on demand */
  41. struct nbs_pvt {
  42. NBS *nbs;
  43. struct ast_channel *owner; /* Channel we belong to, possibly NULL */
  44. char app[16]; /* Our app */
  45. char stream[80]; /* Our stream */
  46. struct ast_frame fr; /* "null" frame */
  47. };
  48. static int nbs_call(struct ast_channel *ast, char *dest, int timeout)
  49. {
  50. struct nbs_pvt *p;
  51. p = ast->pvt->pvt;
  52. if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
  53. ast_log(LOG_WARNING, "nbs_call called on %s, neither down nor reserved\n", ast->name);
  54. return -1;
  55. }
  56. /* When we call, it just works, really, there's no destination... Just
  57. ring the phone and wait for someone to answer */
  58. if (option_debug)
  59. ast_log(LOG_DEBUG, "Calling %s on %s\n", dest, ast->name);
  60. /* If we can't connect, return congestion */
  61. if (nbs_connect(p->nbs)) {
  62. ast_log(LOG_WARNING, "NBS Connection failed on %s\n", ast->name);
  63. ast_queue_control(ast, AST_CONTROL_CONGESTION);
  64. } else {
  65. ast_setstate(ast, AST_STATE_RINGING);
  66. ast_queue_control(ast, AST_CONTROL_ANSWER);
  67. }
  68. return 0;
  69. }
  70. static void nbs_destroy(struct nbs_pvt *p)
  71. {
  72. if (p->nbs)
  73. nbs_delstream(p->nbs);
  74. free(p);
  75. }
  76. static struct nbs_pvt *nbs_alloc(void *data)
  77. {
  78. struct nbs_pvt *p;
  79. int flags = 0;
  80. char stream[256] = "";
  81. char *opts;
  82. strncpy(stream, data, sizeof(stream) - 1);
  83. if ((opts = strchr(stream, ':'))) {
  84. *opts = '\0';
  85. opts++;
  86. } else
  87. opts = "";
  88. p = malloc(sizeof(struct nbs_pvt));
  89. if (p) {
  90. memset(p, 0, sizeof(struct nbs_pvt));
  91. if (strlen(opts)) {
  92. if (strchr(opts, 'm'))
  93. flags |= NBS_FLAG_MUTE;
  94. if (strchr(opts, 'o'))
  95. flags |= NBS_FLAG_OVERSPEAK;
  96. if (strchr(opts, 'e'))
  97. flags |= NBS_FLAG_EMERGENCY;
  98. if (strchr(opts, 'O'))
  99. flags |= NBS_FLAG_OVERRIDE;
  100. } else
  101. flags = NBS_FLAG_OVERSPEAK;
  102. strncpy(p->stream, stream, sizeof(p->stream) - 1);
  103. p->nbs = nbs_newstream("asterisk", stream, flags);
  104. if (!p->nbs) {
  105. ast_log(LOG_WARNING, "Unable to allocate new NBS stream '%s' with flags %d\n", stream, flags);
  106. free(p);
  107. p = NULL;
  108. } else {
  109. /* Set for 8000 hz mono, 640 samples */
  110. nbs_setbitrate(p->nbs, 8000);
  111. nbs_setchannels(p->nbs, 1);
  112. nbs_setblocksize(p->nbs, 640);
  113. nbs_setblocking(p->nbs, 0);
  114. }
  115. }
  116. return p;
  117. }
  118. static int nbs_hangup(struct ast_channel *ast)
  119. {
  120. struct nbs_pvt *p;
  121. p = ast->pvt->pvt;
  122. if (option_debug)
  123. ast_log(LOG_DEBUG, "nbs_hangup(%s)\n", ast->name);
  124. if (!ast->pvt->pvt) {
  125. ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
  126. return 0;
  127. }
  128. nbs_destroy(p);
  129. ast->pvt->pvt = NULL;
  130. ast_setstate(ast, AST_STATE_DOWN);
  131. return 0;
  132. }
  133. static struct ast_frame *nbs_xread(struct ast_channel *ast)
  134. {
  135. struct nbs_pvt *p = ast->pvt->pvt;
  136. /* Some nice norms */
  137. p->fr.datalen = 0;
  138. p->fr.samples = 0;
  139. p->fr.data = NULL;
  140. p->fr.src = type;
  141. p->fr.offset = 0;
  142. p->fr.mallocd=0;
  143. p->fr.delivery.tv_sec = 0;
  144. p->fr.delivery.tv_usec = 0;
  145. ast_log(LOG_DEBUG, "Returning null frame on %s\n", ast->name);
  146. return &p->fr;
  147. }
  148. static int nbs_xwrite(struct ast_channel *ast, struct ast_frame *frame)
  149. {
  150. struct nbs_pvt *p = ast->pvt->pvt;
  151. /* Write a frame of (presumably voice) data */
  152. if (frame->frametype != AST_FRAME_VOICE) {
  153. if (frame->frametype != AST_FRAME_IMAGE)
  154. ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
  155. return 0;
  156. }
  157. if (!(frame->subclass &
  158. (AST_FORMAT_SLINEAR))) {
  159. ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
  160. return 0;
  161. }
  162. if (ast->_state != AST_STATE_UP) {
  163. /* Don't try tos end audio on-hook */
  164. return 0;
  165. }
  166. if (nbs_write(p->nbs, frame->data, frame->datalen / 2) < 0)
  167. return -1;
  168. return 0;
  169. }
  170. static struct ast_channel *nbs_new(struct nbs_pvt *i, int state)
  171. {
  172. struct ast_channel *tmp;
  173. tmp = ast_channel_alloc(1);
  174. if (tmp) {
  175. snprintf(tmp->name, sizeof(tmp->name), "NBS/%s", i->stream);
  176. tmp->type = type;
  177. tmp->fds[0] = nbs_fd(i->nbs);
  178. tmp->nativeformats = prefformat;
  179. tmp->pvt->rawreadformat = prefformat;
  180. tmp->pvt->rawwriteformat = prefformat;
  181. tmp->writeformat = prefformat;
  182. tmp->readformat = prefformat;
  183. ast_setstate(tmp, state);
  184. if (state == AST_STATE_RING)
  185. tmp->rings = 1;
  186. tmp->pvt->pvt = i;
  187. tmp->pvt->call = nbs_call;
  188. tmp->pvt->hangup = nbs_hangup;
  189. tmp->pvt->read = nbs_xread;
  190. tmp->pvt->write = nbs_xwrite;
  191. strncpy(tmp->context, context, sizeof(tmp->context)-1);
  192. strncpy(tmp->exten, "s", sizeof(tmp->exten) - 1);
  193. tmp->language[0] = '\0';
  194. i->owner = tmp;
  195. ast_mutex_lock(&usecnt_lock);
  196. usecnt++;
  197. ast_mutex_unlock(&usecnt_lock);
  198. ast_update_use_count();
  199. if (state != AST_STATE_DOWN) {
  200. if (ast_pbx_start(tmp)) {
  201. ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
  202. ast_hangup(tmp);
  203. }
  204. }
  205. } else
  206. ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
  207. return tmp;
  208. }
  209. static struct ast_channel *nbs_request(char *type, int format, void *data)
  210. {
  211. int oldformat;
  212. struct nbs_pvt *p;
  213. struct ast_channel *tmp = NULL;
  214. oldformat = format;
  215. format &= (AST_FORMAT_SLINEAR);
  216. if (!format) {
  217. ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", oldformat);
  218. return NULL;
  219. }
  220. p = nbs_alloc(data);
  221. if (p) {
  222. tmp = nbs_new(p, AST_STATE_DOWN);
  223. if (!tmp)
  224. nbs_destroy(p);
  225. }
  226. return tmp;
  227. }
  228. static int __unload_module(void)
  229. {
  230. /* First, take us out of the channel loop */
  231. ast_channel_unregister(type);
  232. return 0;
  233. }
  234. int unload_module(void)
  235. {
  236. return __unload_module();
  237. }
  238. int load_module()
  239. {
  240. /* Make sure we can register our Adtranphone channel type */
  241. if (ast_channel_register(type, tdesc,
  242. AST_FORMAT_SLINEAR, nbs_request)) {
  243. ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
  244. __unload_module();
  245. return -1;
  246. }
  247. return 0;
  248. }
  249. int usecount()
  250. {
  251. int res;
  252. ast_mutex_lock(&usecnt_lock);
  253. res = usecnt;
  254. ast_mutex_unlock(&usecnt_lock);
  255. return res;
  256. }
  257. char *description()
  258. {
  259. return desc;
  260. }
  261. char *key()
  262. {
  263. return ASTERISK_GPL_KEY;
  264. }