format_vox.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. /*
  2. * Asterisk -- A telephony toolkit for Linux.
  3. *
  4. * Flat, binary, ADPCM vox file format.
  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 <asterisk/lock.h>
  14. #include <asterisk/channel.h>
  15. #include <asterisk/file.h>
  16. #include <asterisk/logger.h>
  17. #include <asterisk/sched.h>
  18. #include <asterisk/module.h>
  19. #include <netinet/in.h>
  20. #include <arpa/inet.h>
  21. #include <stdlib.h>
  22. #include <sys/time.h>
  23. #include <stdio.h>
  24. #include <unistd.h>
  25. #include <errno.h>
  26. #include <string.h>
  27. #include <pthread.h>
  28. #ifdef __linux__
  29. #include <endian.h>
  30. #else
  31. #include <machine/endian.h>
  32. #endif
  33. #define BUF_SIZE 80 /* 160 samples */
  34. struct ast_filestream {
  35. void *reserved[AST_RESERVED_POINTERS];
  36. /* This is what a filestream means to us */
  37. int fd; /* Descriptor */
  38. struct ast_frame fr; /* Frame information */
  39. char waste[AST_FRIENDLY_OFFSET]; /* Buffer for sending frames, etc */
  40. char empty; /* Empty character */
  41. unsigned char buf[BUF_SIZE]; /* Output Buffer */
  42. int lasttimeout;
  43. struct timeval last;
  44. short signal; /* Signal level (file side) */
  45. short ssindex; /* Signal ssindex (file side) */
  46. unsigned char zero_count; /* counter of consecutive zero samples */
  47. unsigned char next_flag;
  48. };
  49. static ast_mutex_t vox_lock = AST_MUTEX_INITIALIZER;
  50. static int glistcnt = 0;
  51. static char *name = "vox";
  52. static char *desc = "Dialogic VOX (ADPCM) File Format";
  53. static char *exts = "vox";
  54. static struct ast_filestream *vox_open(int fd)
  55. {
  56. /* We don't have any header to read or anything really, but
  57. if we did, it would go here. We also might want to check
  58. and be sure it's a valid file. */
  59. struct ast_filestream *tmp;
  60. if ((tmp = malloc(sizeof(struct ast_filestream)))) {
  61. memset(tmp, 0, sizeof(struct ast_filestream));
  62. if (ast_mutex_lock(&vox_lock)) {
  63. ast_log(LOG_WARNING, "Unable to lock vox list\n");
  64. free(tmp);
  65. return NULL;
  66. }
  67. tmp->fd = fd;
  68. tmp->fr.data = tmp->buf;
  69. tmp->fr.frametype = AST_FRAME_VOICE;
  70. tmp->fr.subclass = AST_FORMAT_ADPCM;
  71. /* datalen will vary for each frame */
  72. tmp->fr.src = name;
  73. tmp->fr.mallocd = 0;
  74. tmp->lasttimeout = -1;
  75. glistcnt++;
  76. ast_mutex_unlock(&vox_lock);
  77. ast_update_use_count();
  78. }
  79. return tmp;
  80. }
  81. static struct ast_filestream *vox_rewrite(int fd, char *comment)
  82. {
  83. /* We don't have any header to read or anything really, but
  84. if we did, it would go here. We also might want to check
  85. and be sure it's a valid file. */
  86. struct ast_filestream *tmp;
  87. if ((tmp = malloc(sizeof(struct ast_filestream)))) {
  88. memset(tmp, 0, sizeof(struct ast_filestream));
  89. if (ast_mutex_lock(&vox_lock)) {
  90. ast_log(LOG_WARNING, "Unable to lock vox list\n");
  91. free(tmp);
  92. return NULL;
  93. }
  94. tmp->fd = fd;
  95. glistcnt++;
  96. ast_mutex_unlock(&vox_lock);
  97. ast_update_use_count();
  98. } else
  99. ast_log(LOG_WARNING, "Out of memory\n");
  100. return tmp;
  101. }
  102. static void vox_close(struct ast_filestream *s)
  103. {
  104. if (ast_mutex_lock(&vox_lock)) {
  105. ast_log(LOG_WARNING, "Unable to lock vox list\n");
  106. return;
  107. }
  108. glistcnt--;
  109. ast_mutex_unlock(&vox_lock);
  110. ast_update_use_count();
  111. close(s->fd);
  112. free(s);
  113. s = NULL;
  114. }
  115. static struct ast_frame *vox_read(struct ast_filestream *s, int *whennext)
  116. {
  117. int res;
  118. /* Send a frame from the file to the appropriate channel */
  119. s->fr.frametype = AST_FRAME_VOICE;
  120. s->fr.subclass = AST_FORMAT_ADPCM;
  121. s->fr.offset = AST_FRIENDLY_OFFSET;
  122. s->fr.mallocd = 0;
  123. s->fr.data = s->buf;
  124. if ((res = read(s->fd, s->buf, BUF_SIZE)) < 1) {
  125. if (res)
  126. ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
  127. return NULL;
  128. }
  129. s->fr.samples = res * 2;
  130. s->fr.datalen = res;
  131. *whennext = s->fr.samples;
  132. return &s->fr;
  133. }
  134. static int vox_write(struct ast_filestream *fs, struct ast_frame *f)
  135. {
  136. int res;
  137. if (f->frametype != AST_FRAME_VOICE) {
  138. ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
  139. return -1;
  140. }
  141. if (f->subclass != AST_FORMAT_ADPCM) {
  142. ast_log(LOG_WARNING, "Asked to write non-ADPCM frame (%d)!\n", f->subclass);
  143. return -1;
  144. }
  145. if ((res = write(fs->fd, f->data, f->datalen)) != f->datalen) {
  146. ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n", res, f->datalen, strerror(errno));
  147. return -1;
  148. }
  149. return 0;
  150. }
  151. static char *vox_getcomment(struct ast_filestream *s)
  152. {
  153. return NULL;
  154. }
  155. static int vox_seek(struct ast_filestream *fs, long sample_offset, int whence)
  156. {
  157. return -1;
  158. }
  159. static int vox_trunc(struct ast_filestream *fs)
  160. {
  161. return -1;
  162. }
  163. static long vox_tell(struct ast_filestream *fs)
  164. {
  165. return -1;
  166. }
  167. int load_module()
  168. {
  169. return ast_format_register(name, exts, AST_FORMAT_ADPCM,
  170. vox_open,
  171. vox_rewrite,
  172. vox_write,
  173. vox_seek,
  174. vox_trunc,
  175. vox_tell,
  176. vox_read,
  177. vox_close,
  178. vox_getcomment);
  179. }
  180. int unload_module()
  181. {
  182. return ast_format_unregister(name);
  183. }
  184. int usecount()
  185. {
  186. int res;
  187. if (ast_mutex_lock(&vox_lock)) {
  188. ast_log(LOG_WARNING, "Unable to lock vox list\n");
  189. return -1;
  190. }
  191. res = glistcnt;
  192. ast_mutex_unlock(&vox_lock);
  193. return res;
  194. }
  195. char *description()
  196. {
  197. return desc;
  198. }
  199. char *key()
  200. {
  201. return ASTERISK_GPL_KEY;
  202. }