sip-lab 1.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +38 -0
  2. package/a.js +280 -0
  3. package/binding.gyp +101 -0
  4. package/devjournal +435 -0
  5. package/index.js +68 -0
  6. package/install.sh +32 -0
  7. package/package.json +30 -0
  8. package/samples/late_negotiation.js +278 -0
  9. package/samples/simple.js +280 -0
  10. package/samples/sip_cancel.js +111 -0
  11. package/src/Makefile +42 -0
  12. package/src/README +3 -0
  13. package/src/addon.cpp +1418 -0
  14. package/src/event_templates.cpp +55 -0
  15. package/src/event_templates.hpp +27 -0
  16. package/src/idmanager.cpp +76 -0
  17. package/src/idmanager.hpp +26 -0
  18. package/src/log.cpp +18 -0
  19. package/src/log.hpp +15 -0
  20. package/src/packetdumper.cpp +234 -0
  21. package/src/packetdumper.hpp +67 -0
  22. package/src/pjmedia/Makefile +37 -0
  23. package/src/pjmedia/devjournal +26 -0
  24. package/src/pjmedia/include/chainlink/README +3 -0
  25. package/src/pjmedia/include/chainlink/chainlink.h +11 -0
  26. package/src/pjmedia/include/chainlink/chainlink_dtmfdet.h +56 -0
  27. package/src/pjmedia/include/chainlink/chainlink_tonegen.h +178 -0
  28. package/src/pjmedia/include/chainlink/chainlink_wav_port.h +231 -0
  29. package/src/pjmedia/include/chainlink/chainlink_wire_port.h +50 -0
  30. package/src/pjmedia/include/pjmedia/README +3 -0
  31. package/src/pjmedia/include/pjmedia/dtmfdet.h +74 -0
  32. package/src/pjmedia/src/chainlink/chainlink_dtmfdet.c +125 -0
  33. package/src/pjmedia/src/chainlink/chainlink_tonegen.c +901 -0
  34. package/src/pjmedia/src/chainlink/chainlink_wav_player.c +688 -0
  35. package/src/pjmedia/src/chainlink/chainlink_wav_writer.c +442 -0
  36. package/src/pjmedia/src/chainlink/chainlink_wire_port.c +93 -0
  37. package/src/pjmedia/src/pjmedia/dtmfdet.c +129 -0
  38. package/src/pjmedia/src/pjmedia/simpleua_dtmfdet.c +753 -0
  39. package/src/pjmedia/src/pjmedia/tonegen_dtmfdet.c +263 -0
  40. package/src/sip.cpp +4891 -0
  41. package/src/sip.hpp +64 -0
@@ -0,0 +1,442 @@
1
+ #include "chainlink.h"
2
+ #include "chainlink_wav_port.h"
3
+
4
+ #include <pjmedia/wav_port.h>
5
+ #include <pjmedia/alaw_ulaw.h>
6
+ #include <pjmedia/errno.h>
7
+ #include <pjmedia/wave.h>
8
+ #include <pj/assert.h>
9
+ #include <pj/file_access.h>
10
+ #include <pj/file_io.h>
11
+ #include <pj/log.h>
12
+ #include <pj/pool.h>
13
+ #include <pj/string.h>
14
+
15
+
16
+ #define THIS_FILE "chainlink_wav_writer.c"
17
+ #define SIGNATURE PJMEDIA_SIGNATURE('L', 'w', 'w', 'r')
18
+
19
+
20
+ struct file_port
21
+ {
22
+ struct chainlink link;
23
+ pjmedia_wave_fmt_tag fmt_tag;
24
+ pj_uint16_t bytes_per_sample;
25
+
26
+ pj_size_t bufsize;
27
+ char *buf;
28
+ char *writepos;
29
+ pj_size_t total;
30
+
31
+ pj_oshandle_t fd;
32
+
33
+ pj_size_t cb_size;
34
+ pj_status_t (*cb)(pjmedia_port*, void*);
35
+ };
36
+
37
+ static pj_status_t file_put_frame(pjmedia_port *this_port,
38
+ pjmedia_frame *frame);
39
+ static pj_status_t file_get_frame(pjmedia_port *this_port,
40
+ pjmedia_frame *frame);
41
+ static pj_status_t file_on_destroy(pjmedia_port *this_port);
42
+
43
+
44
+ /*
45
+ * Create file writer port.
46
+ */
47
+ PJ_DEF(pj_status_t) chainlink_wav_writer_port_create( pj_pool_t *pool,
48
+ const char *filename,
49
+ unsigned sampling_rate,
50
+ unsigned channel_count,
51
+ unsigned samples_per_frame,
52
+ unsigned bits_per_sample,
53
+ unsigned flags,
54
+ pj_ssize_t buff_size,
55
+ pjmedia_port **p_port )
56
+ {
57
+ struct file_port *fport;
58
+ pjmedia_wave_hdr wave_hdr;
59
+ pj_ssize_t size;
60
+ pj_str_t name;
61
+ pj_status_t status;
62
+
63
+ /* Check arguments. */
64
+ PJ_ASSERT_RETURN(pool && filename && p_port, PJ_EINVAL);
65
+
66
+ /* Only supports 16bits per sample for now.
67
+ * See flush_buffer().
68
+ */
69
+ PJ_ASSERT_RETURN(bits_per_sample == 16, PJ_EINVAL);
70
+
71
+ /* Create file port instance. */
72
+ fport = PJ_POOL_ZALLOC_T(pool, struct file_port);
73
+ PJ_ASSERT_RETURN(fport != NULL, PJ_ENOMEM);
74
+
75
+ /* Initialize port info. */
76
+ pj_strdup2(pool, &name, filename);
77
+ pjmedia_port_info_init(&fport->link.port.info, &name, SIGNATURE,
78
+ sampling_rate, channel_count, bits_per_sample,
79
+ samples_per_frame);
80
+
81
+ fport->link.port.get_frame = &file_get_frame;
82
+ fport->link.port.put_frame = &file_put_frame;
83
+ fport->link.port.on_destroy = &file_on_destroy;
84
+
85
+ if (flags == PJMEDIA_FILE_WRITE_ALAW) {
86
+ fport->fmt_tag = PJMEDIA_WAVE_FMT_TAG_ALAW;
87
+ fport->bytes_per_sample = 1;
88
+ } else if (flags == PJMEDIA_FILE_WRITE_ULAW) {
89
+ fport->fmt_tag = PJMEDIA_WAVE_FMT_TAG_ULAW;
90
+ fport->bytes_per_sample = 1;
91
+ } else {
92
+ fport->fmt_tag = PJMEDIA_WAVE_FMT_TAG_PCM;
93
+ fport->bytes_per_sample = 2;
94
+ }
95
+
96
+ /* Open file in write and read mode.
97
+ * We need the read mode because we'll modify the WAVE header once
98
+ * the recording has completed.
99
+ */
100
+ status = pj_file_open(pool, filename, PJ_O_WRONLY, &fport->fd);
101
+ if (status != PJ_SUCCESS)
102
+ return status;
103
+
104
+ /* Initialize WAVE header */
105
+ pj_bzero(&wave_hdr, sizeof(pjmedia_wave_hdr));
106
+ wave_hdr.riff_hdr.riff = PJMEDIA_RIFF_TAG;
107
+ wave_hdr.riff_hdr.file_len = 0; /* will be filled later */
108
+ wave_hdr.riff_hdr.wave = PJMEDIA_WAVE_TAG;
109
+
110
+ wave_hdr.fmt_hdr.fmt = PJMEDIA_FMT_TAG;
111
+ wave_hdr.fmt_hdr.len = 16;
112
+ wave_hdr.fmt_hdr.fmt_tag = (pj_uint16_t)fport->fmt_tag;
113
+ wave_hdr.fmt_hdr.nchan = (pj_int16_t)channel_count;
114
+ wave_hdr.fmt_hdr.sample_rate = sampling_rate;
115
+ wave_hdr.fmt_hdr.bytes_per_sec = sampling_rate * channel_count *
116
+ fport->bytes_per_sample;
117
+ wave_hdr.fmt_hdr.block_align = (pj_uint16_t)
118
+ (fport->bytes_per_sample * channel_count);
119
+ wave_hdr.fmt_hdr.bits_per_sample = (pj_uint16_t)
120
+ (fport->bytes_per_sample * 8);
121
+
122
+ wave_hdr.data_hdr.data = PJMEDIA_DATA_TAG;
123
+ wave_hdr.data_hdr.len = 0; /* will be filled later */
124
+
125
+
126
+ /* Convert WAVE header from host byte order to little endian
127
+ * before writing the header.
128
+ */
129
+ pjmedia_wave_hdr_host_to_file(&wave_hdr);
130
+
131
+
132
+ /* Write WAVE header */
133
+ if (fport->fmt_tag != PJMEDIA_WAVE_FMT_TAG_PCM) {
134
+ pjmedia_wave_subchunk fact_chunk;
135
+ pj_uint32_t tmp = 0;
136
+
137
+ fact_chunk.id = PJMEDIA_FACT_TAG;
138
+ fact_chunk.len = 4;
139
+
140
+ PJMEDIA_WAVE_NORMALIZE_SUBCHUNK(&fact_chunk);
141
+
142
+ /* Write WAVE header without DATA chunk header */
143
+ size = sizeof(pjmedia_wave_hdr) - sizeof(wave_hdr.data_hdr);
144
+ status = pj_file_write(fport->fd, &wave_hdr, &size);
145
+ if (status != PJ_SUCCESS) {
146
+ pj_file_close(fport->fd);
147
+ return status;
148
+ }
149
+
150
+ /* Write FACT chunk if it stores compressed data */
151
+ size = sizeof(fact_chunk);
152
+ status = pj_file_write(fport->fd, &fact_chunk, &size);
153
+ if (status != PJ_SUCCESS) {
154
+ pj_file_close(fport->fd);
155
+ return status;
156
+ }
157
+ size = 4;
158
+ status = pj_file_write(fport->fd, &tmp, &size);
159
+ if (status != PJ_SUCCESS) {
160
+ pj_file_close(fport->fd);
161
+ return status;
162
+ }
163
+
164
+ /* Write DATA chunk header */
165
+ size = sizeof(wave_hdr.data_hdr);
166
+ status = pj_file_write(fport->fd, &wave_hdr.data_hdr, &size);
167
+ if (status != PJ_SUCCESS) {
168
+ pj_file_close(fport->fd);
169
+ return status;
170
+ }
171
+ } else {
172
+ size = sizeof(pjmedia_wave_hdr);
173
+ status = pj_file_write(fport->fd, &wave_hdr, &size);
174
+ if (status != PJ_SUCCESS) {
175
+ pj_file_close(fport->fd);
176
+ return status;
177
+ }
178
+ }
179
+
180
+ /* Set buffer size. */
181
+ if (buff_size < 1) buff_size = PJMEDIA_FILE_PORT_BUFSIZE;
182
+ fport->bufsize = buff_size;
183
+
184
+ /* Check that buffer size is greater than bytes per frame */
185
+ pj_assert(fport->bufsize >= PJMEDIA_PIA_AVG_FSZ(&fport->link.port.info));
186
+
187
+
188
+ /* Allocate buffer and set initial write position */
189
+ fport->buf = (char*) pj_pool_alloc(pool, fport->bufsize);
190
+ if (fport->buf == NULL) {
191
+ pj_file_close(fport->fd);
192
+ return PJ_ENOMEM;
193
+ }
194
+ fport->writepos = fport->buf;
195
+
196
+ /* Done. */
197
+ *p_port = &fport->link.port;
198
+
199
+ PJ_LOG(4,(THIS_FILE,
200
+ "File writer '%.*s' created: samp.rate=%d, bufsize=%uKB",
201
+ (int)fport->link.port.info.name.slen,
202
+ fport->link.port.info.name.ptr,
203
+ PJMEDIA_PIA_SRATE(&fport->link.port.info),
204
+ fport->bufsize / 1000));
205
+
206
+
207
+ return PJ_SUCCESS;
208
+ }
209
+
210
+
211
+
212
+ /*
213
+ * Get current writing position.
214
+ */
215
+ PJ_DEF(pj_ssize_t) chainlink_wav_writer_port_get_pos( pjmedia_port *port )
216
+ {
217
+ struct file_port *fport;
218
+
219
+ /* Sanity check */
220
+ PJ_ASSERT_RETURN(port, -PJ_EINVAL);
221
+
222
+ /* Check that this is really a writer port */
223
+ PJ_ASSERT_RETURN(port->info.signature == SIGNATURE, -PJ_EINVALIDOP);
224
+
225
+ fport = (struct file_port*) port;
226
+
227
+ return fport->total;
228
+ }
229
+
230
+
231
+ /*
232
+ * Register callback.
233
+ */
234
+ PJ_DEF(pj_status_t) chainlink_wav_writer_port_set_cb( pjmedia_port *port,
235
+ pj_size_t pos,
236
+ void *user_data,
237
+ pj_status_t (*cb)(pjmedia_port *port,
238
+ void *usr_data))
239
+ {
240
+ struct file_port *fport;
241
+
242
+ /* Sanity check */
243
+ PJ_ASSERT_RETURN(port && cb, PJ_EINVAL);
244
+
245
+ /* Check that this is really a writer port */
246
+ PJ_ASSERT_RETURN(port->info.signature == SIGNATURE, PJ_EINVALIDOP);
247
+
248
+ fport = (struct file_port*) port;
249
+
250
+ fport->cb_size = pos;
251
+ fport->link.port.port_data.pdata = user_data;
252
+ fport->cb = cb;
253
+
254
+ return PJ_SUCCESS;
255
+ }
256
+
257
+
258
+ #if defined(PJ_IS_BIG_ENDIAN) && PJ_IS_BIG_ENDIAN!=0
259
+ static void swap_samples(pj_int16_t *samples, unsigned count)
260
+ {
261
+ unsigned i;
262
+ for (i=0; i<count; ++i) {
263
+ samples[i] = pj_swap16(samples[i]);
264
+ }
265
+ }
266
+ #else
267
+ # define swap_samples(samples,count)
268
+ #endif
269
+
270
+ /*
271
+ * Flush the contents of the buffer to the file.
272
+ */
273
+ static pj_status_t flush_buffer(struct file_port *fport)
274
+ {
275
+ pj_ssize_t bytes = fport->writepos - fport->buf;
276
+ pj_status_t status;
277
+
278
+ /* Convert samples to little endian */
279
+ swap_samples((pj_int16_t*)fport->buf, bytes/fport->bytes_per_sample);
280
+
281
+ /* Write to file. */
282
+ status = pj_file_write(fport->fd, fport->buf, &bytes);
283
+
284
+ /* Reset writepos */
285
+ fport->writepos = fport->buf;
286
+
287
+ return status;
288
+ }
289
+
290
+ /*
291
+ * Put a frame into the buffer. When the buffer is full, flush the buffer
292
+ * to the file.
293
+ */
294
+ static pj_status_t file_put_frame(pjmedia_port *this_port,
295
+ pjmedia_frame *frame)
296
+ {
297
+ struct file_port *fport = (struct file_port *)this_port;
298
+ unsigned frame_size;
299
+
300
+ if (fport->fmt_tag == PJMEDIA_WAVE_FMT_TAG_PCM)
301
+ frame_size = frame->size;
302
+ else
303
+ frame_size = frame->size >> 1;
304
+
305
+ /* Flush buffer if we don't have enough room for the frame. */
306
+ if (fport->writepos + frame_size > fport->buf + fport->bufsize) {
307
+ pj_status_t status;
308
+ status = flush_buffer(fport);
309
+ if (status != PJ_SUCCESS)
310
+ return status;
311
+ }
312
+
313
+ /* Check if frame is not too large. */
314
+ PJ_ASSERT_RETURN(fport->writepos+frame_size <= fport->buf+fport->bufsize,
315
+ PJMEDIA_EFRMFILETOOBIG);
316
+
317
+ /* Copy frame to buffer. */
318
+ if (fport->fmt_tag == PJMEDIA_WAVE_FMT_TAG_PCM) {
319
+ pj_memcpy(fport->writepos, frame->buf, frame->size);
320
+ } else {
321
+ unsigned i;
322
+ pj_int16_t *src = (pj_int16_t*)frame->buf;
323
+ pj_uint8_t *dst = (pj_uint8_t*)fport->writepos;
324
+
325
+ if (fport->fmt_tag == PJMEDIA_WAVE_FMT_TAG_ULAW) {
326
+ for (i = 0; i < frame_size; ++i) {
327
+ *dst++ = pjmedia_linear2ulaw(*src++);
328
+ }
329
+ } else {
330
+ for (i = 0; i < frame_size; ++i) {
331
+ *dst++ = pjmedia_linear2alaw(*src++);
332
+ }
333
+ }
334
+
335
+ }
336
+ fport->writepos += frame_size;
337
+
338
+ /* Increment total written, and check if we need to call callback */
339
+ fport->total += frame_size;
340
+ if (fport->cb && fport->total >= fport->cb_size) {
341
+ pj_status_t (*cb)(pjmedia_port*, void*);
342
+ pj_status_t status;
343
+
344
+ cb = fport->cb;
345
+ fport->cb = NULL;
346
+
347
+ status = (*cb)(this_port, this_port->port_data.pdata);
348
+ return status;
349
+ }
350
+
351
+ return PJ_SUCCESS;
352
+ }
353
+
354
+ static pj_status_t file_get_frame(pjmedia_port *this_port,
355
+ pjmedia_frame *frame)
356
+ {
357
+ PJ_ASSERT_RETURN(this_port && frame, PJ_EINVAL);
358
+
359
+ struct chainlink *link = (struct chainlink*)this_port;
360
+ PJ_ASSERT_RETURN(link->next, PJ_EINVAL);
361
+ PJ_ASSERT_RETURN(link->next->get_frame, PJ_EINVAL);
362
+
363
+ return link->next->get_frame(link->next, frame);
364
+ }
365
+
366
+ /*
367
+ * Close the port, modify file header with updated file length.
368
+ */
369
+ static pj_status_t file_on_destroy(pjmedia_port *this_port)
370
+ {
371
+ enum { FILE_LEN_POS = 4, DATA_LEN_POS = 40 };
372
+ struct file_port *fport = (struct file_port *)this_port;
373
+ pj_off_t file_size;
374
+ pj_ssize_t bytes;
375
+ pj_uint32_t wave_file_len;
376
+ pj_uint32_t wave_data_len;
377
+ pj_status_t status;
378
+ pj_uint32_t data_len_pos = DATA_LEN_POS;
379
+
380
+ /* Flush remaining buffers. */
381
+ if (fport->writepos != fport->buf)
382
+ flush_buffer(fport);
383
+
384
+ /* Get file size. */
385
+ status = pj_file_getpos(fport->fd, &file_size);
386
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
387
+
388
+ /* Calculate wave fields */
389
+ wave_file_len = (pj_uint32_t)(file_size - 8);
390
+ wave_data_len = (pj_uint32_t)(file_size - sizeof(pjmedia_wave_hdr));
391
+
392
+ #if defined(PJ_IS_BIG_ENDIAN) && PJ_IS_BIG_ENDIAN!=0
393
+ wave_file_len = pj_swap32(wave_file_len);
394
+ wave_data_len = pj_swap32(wave_data_len);
395
+ #endif
396
+
397
+ /* Seek to the file_len field. */
398
+ status = pj_file_setpos(fport->fd, FILE_LEN_POS, PJ_SEEK_SET);
399
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
400
+
401
+ /* Write file_len */
402
+ bytes = sizeof(wave_file_len);
403
+ status = pj_file_write(fport->fd, &wave_file_len, &bytes);
404
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
405
+
406
+ /* Write samples_len in FACT chunk */
407
+ if (fport->fmt_tag != PJMEDIA_WAVE_FMT_TAG_PCM) {
408
+ enum { SAMPLES_LEN_POS = 44};
409
+ pj_uint32_t wav_samples_len;
410
+
411
+ /* Adjust wave_data_len & data_len_pos since there is FACT chunk */
412
+ wave_data_len -= 12;
413
+ data_len_pos += 12;
414
+ wav_samples_len = wave_data_len;
415
+
416
+ /* Seek to samples_len field. */
417
+ status = pj_file_setpos(fport->fd, SAMPLES_LEN_POS, PJ_SEEK_SET);
418
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
419
+
420
+ /* Write samples_len */
421
+ bytes = sizeof(wav_samples_len);
422
+ status = pj_file_write(fport->fd, &wav_samples_len, &bytes);
423
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
424
+ }
425
+
426
+ /* Seek to data_len field. */
427
+ status = pj_file_setpos(fport->fd, data_len_pos, PJ_SEEK_SET);
428
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
429
+
430
+ /* Write file_len */
431
+ bytes = sizeof(wave_data_len);
432
+ status = pj_file_write(fport->fd, &wave_data_len, &bytes);
433
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
434
+
435
+ /* Close file */
436
+ status = pj_file_close(fport->fd);
437
+ PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
438
+
439
+ /* Done. */
440
+ return PJ_SUCCESS;
441
+ }
442
+
@@ -0,0 +1,93 @@
1
+ #include "chainlink.h"
2
+ #include "chainlink_wire_port.h"
3
+
4
+ #include <pjmedia/errno.h>
5
+ #include <pj/assert.h>
6
+ #include <pj/pool.h>
7
+ #include <pj/string.h>
8
+
9
+ #define SIGNATURE PJMEDIA_SIGNATURE('L', 'w', 'i', 'r')
10
+
11
+ static pj_status_t wire_get_frame(pjmedia_port *this_port,
12
+ pjmedia_frame *frame);
13
+ static pj_status_t wire_put_frame(pjmedia_port *this_port,
14
+ pjmedia_frame *frame);
15
+ static pj_status_t wire_on_destroy(pjmedia_port *this_port);
16
+
17
+
18
+ PJ_DEF(pj_status_t) chainlink_wire_port_create( pj_pool_t *pool,
19
+ unsigned sampling_rate,
20
+ unsigned channel_count,
21
+ unsigned samples_per_frame,
22
+ unsigned bits_per_sample,
23
+ pjmedia_port **p_port )
24
+ {
25
+ struct chainlink *link;
26
+ const pj_str_t name = pj_str("wire-port");
27
+
28
+ PJ_ASSERT_RETURN(pool && p_port, PJ_EINVAL);
29
+
30
+ link = PJ_POOL_ZALLOC_T(pool, struct chainlink);
31
+ PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM);
32
+
33
+ pjmedia_port_info_init(&link->port.info, &name, SIGNATURE, sampling_rate,
34
+ channel_count, bits_per_sample, samples_per_frame);
35
+
36
+ link->port.get_frame = &wire_get_frame;
37
+ link->port.put_frame = &wire_put_frame;
38
+ link->port.on_destroy = &wire_on_destroy;
39
+
40
+
41
+ *p_port = &link->port;
42
+
43
+ return PJ_SUCCESS;
44
+ }
45
+
46
+
47
+
48
+ /*
49
+ * Put frame to file.
50
+ */
51
+ static pj_status_t wire_put_frame(pjmedia_port *this_port,
52
+ pjmedia_frame *frame)
53
+ {
54
+ //printf("wire_put_frame %x\n", this_port);
55
+ PJ_ASSERT_RETURN(this_port && frame, PJ_EINVAL);
56
+
57
+ struct chainlink *link = (struct chainlink*)this_port;
58
+ PJ_ASSERT_RETURN(link->next, PJ_EINVAL);
59
+ PJ_ASSERT_RETURN(link->next->put_frame, PJ_EINVAL);
60
+
61
+ return link->next->put_frame(link->next, frame);
62
+
63
+ }
64
+
65
+
66
+ /*
67
+ * Get frame from file.
68
+ */
69
+ static pj_status_t wire_get_frame(pjmedia_port *this_port,
70
+ pjmedia_frame *frame)
71
+ {
72
+ //printf("wire_get_frame %x\n", this_port);
73
+ PJ_ASSERT_RETURN(this_port && frame, PJ_EINVAL);
74
+
75
+ struct chainlink *link = (struct chainlink*)this_port;
76
+ PJ_ASSERT_RETURN(link->next, PJ_EINVAL);
77
+ PJ_ASSERT_RETURN(link->next->get_frame, PJ_EINVAL);
78
+
79
+ pj_status_t s = link->next->get_frame(link->next, frame);
80
+ //pj_perror(0, "", s, "");
81
+ //printf("frame type=%i size=%i timestamp=%i bit_info=%i\n", frame->type, frame->size, frame->timestamp, frame->bit_info);
82
+ return s;
83
+ }
84
+
85
+
86
+ /*
87
+ * Destroy port.
88
+ */
89
+ static pj_status_t wire_on_destroy(pjmedia_port *this_port)
90
+ {
91
+ PJ_UNUSED_ARG(this_port);
92
+ return PJ_SUCCESS;
93
+ }
@@ -0,0 +1,129 @@
1
+ /* $Id: dtmfdet.c 0000 2009-05-01 11:26:53Z mayamatakeshi $ */
2
+ /*
3
+ * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
4
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5
+ *
6
+ * This program is free software; you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation; either version 2 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU General Public License
17
+ * along with this program; if not, write to the Free Software
18
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
+ */
20
+
21
+ #include <pjmedia/dtmfdet.h>
22
+ #include <pjmedia/errno.h>
23
+ #include <pj/assert.h>
24
+ #include <pj/pool.h>
25
+ #include <pj/string.h>
26
+
27
+ #include <spandsp.h>
28
+
29
+ #define SIGNATURE PJMEDIA_PORT_SIGNATURE('d', 't', 'd', 't')
30
+ #define THIS_FILE "dtmfdet.c"
31
+
32
+ #if 0
33
+ # define TRACE_(expr) PJ_LOG(4,expr)
34
+ #else
35
+ # define TRACE_(expr)
36
+ #endif
37
+
38
+ static pj_status_t dtmfdet_put_frame(pjmedia_port *this_port,
39
+ const pjmedia_frame *frame);
40
+ static pj_status_t dtmfdet_on_destroy(pjmedia_port *this_port);
41
+
42
+ struct dtmfdet
43
+ {
44
+ pjmedia_port base;
45
+ dtmf_rx_state_t state;
46
+ void (*dtmf_cb)(pjmedia_port*, void*, char);
47
+ void *dtmf_cb_user_data;
48
+ };
49
+
50
+ static void dtmfdet_digit_callback(void *user_data, int code, int level, int delay)
51
+ {
52
+ struct dtmfdet *dport = (struct dtmfdet*) user_data;
53
+ if(!code) return;
54
+
55
+ TRACE_((THIS_FILE, "dtmfdet digit detected: %c", code));
56
+
57
+ if(!dport->dtmf_cb) return;
58
+
59
+ dport->dtmf_cb((pjmedia_port*)dport,
60
+ dport->dtmf_cb_user_data,
61
+ code);
62
+ }
63
+
64
+ PJ_DEF(pj_status_t) pjmedia_dtmfdet_create( pj_pool_t *pool,
65
+ unsigned clock_rate,
66
+ unsigned channel_count,
67
+ unsigned samples_per_frame,
68
+ unsigned bits_per_sample,
69
+ void (*cb)(pjmedia_port*,
70
+ void *user_data,
71
+ char digit),
72
+ void *user_data,
73
+ pjmedia_port **p_port)
74
+ {
75
+ struct dtmfdet *dtmfdet;
76
+ const pj_str_t name = pj_str("dtmfdet");
77
+
78
+ PJ_ASSERT_RETURN(pool && clock_rate && channel_count &&
79
+ samples_per_frame && bits_per_sample == 16 &&
80
+ p_port != NULL, PJ_EINVAL);
81
+
82
+ PJ_ASSERT_RETURN(pool && p_port, PJ_EINVAL);
83
+
84
+ dtmfdet = PJ_POOL_ZALLOC_T(pool, struct dtmfdet);
85
+ PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM);
86
+
87
+ pjmedia_port_info_init(&dtmfdet->base.info, &name, SIGNATURE, clock_rate,
88
+ channel_count, bits_per_sample, samples_per_frame);
89
+
90
+ dtmfdet->base.put_frame = &dtmfdet_put_frame;
91
+ dtmfdet->base.on_destroy = &dtmfdet_on_destroy;
92
+
93
+ dtmfdet->dtmf_cb = cb;
94
+ dtmfdet->dtmf_cb_user_data = user_data;
95
+
96
+ dtmf_rx_init(&dtmfdet->state, NULL, NULL);
97
+ dtmf_rx_set_realtime_callback(&dtmfdet->state,
98
+ &dtmfdet_digit_callback,
99
+ (void*)dtmfdet);
100
+
101
+ TRACE_((THIS_FILE, "dtmfdet created: %u/%u/%u/%u", clock_rate,
102
+ channel_count, samples_per_frame, bits_per_sample));
103
+
104
+ *p_port = &dtmfdet->base;
105
+ return PJ_SUCCESS;
106
+ }
107
+
108
+ static pj_status_t dtmfdet_put_frame(pjmedia_port *this_port,
109
+ const pjmedia_frame *frame)
110
+ {
111
+ if(frame->type != PJMEDIA_FRAME_TYPE_AUDIO) return PJ_SUCCESS;
112
+
113
+ struct dtmfdet *dport = (struct dtmfdet*) this_port;
114
+ dtmf_rx(&dport->state, (const pj_int16_t*)frame->buf,
115
+ dport->base.info.samples_per_frame);
116
+
117
+ return PJ_SUCCESS;
118
+
119
+ }
120
+
121
+ /*
122
+ * Destroy port.
123
+ */
124
+ static pj_status_t dtmfdet_on_destroy(pjmedia_port *this_port)
125
+ {
126
+ return PJ_SUCCESS;
127
+ }
128
+
129
+