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