format_sln.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. /*
  2. * Asterisk -- A telephony toolkit for Linux.
  3. *
  4. * RAW SLINEAR Format
  5. * Anthony Minessale (anthmct@yahoo.com)
  6. * Derived from format_pcm.c in the asterisk distro
  7. *
  8. * This program is free software, distributed under the terms of
  9. * the GNU General Public License
  10. */
  11. #include <asterisk/lock.h>
  12. #include <asterisk/channel.h>
  13. #include <asterisk/file.h>
  14. #include <asterisk/logger.h>
  15. #include <asterisk/sched.h>
  16. #include <asterisk/module.h>
  17. #include <netinet/in.h>
  18. #include <arpa/inet.h>
  19. #include <stdlib.h>
  20. #include <sys/time.h>
  21. #include <stdio.h>
  22. #include <unistd.h>
  23. #include <errno.h>
  24. #include <string.h>
  25. #ifdef __linux__
  26. #include <endian.h>
  27. #else
  28. #include <machine/endian.h>
  29. #endif
  30. #define BUF_SIZE 320 /* 320 samples */
  31. struct ast_filestream {
  32. void *reserved[AST_RESERVED_POINTERS];
  33. /* This is what a filestream means to us */
  34. int fd; /* Descriptor */
  35. struct ast_channel *owner;
  36. struct ast_frame fr; /* Frame information */
  37. char waste[AST_FRIENDLY_OFFSET]; /* Buffer for sending frames, etc */
  38. char empty; /* Empty character */
  39. unsigned char buf[BUF_SIZE]; /* Output Buffer */
  40. struct timeval last;
  41. };
  42. AST_MUTEX_DEFINE_STATIC(slinear_lock);
  43. static int glistcnt = 0;
  44. static char *name = "sln";
  45. static char *desc = "Raw Signed Linear Audio support (SLN)";
  46. static char *exts = "sln|raw";
  47. static struct ast_filestream *slinear_open(int fd)
  48. {
  49. /* We don't have any header to read or anything really, but
  50. if we did, it would go here. We also might want to check
  51. and be sure it's a valid file. */
  52. struct ast_filestream *tmp;
  53. if ((tmp = malloc(sizeof(struct ast_filestream)))) {
  54. memset(tmp, 0, sizeof(struct ast_filestream));
  55. if (ast_mutex_lock(&slinear_lock)) {
  56. ast_log(LOG_WARNING, "Unable to lock slinear list\n");
  57. free(tmp);
  58. return NULL;
  59. }
  60. tmp->fd = fd;
  61. tmp->fr.data = tmp->buf;
  62. tmp->fr.frametype = AST_FRAME_VOICE;
  63. tmp->fr.subclass = AST_FORMAT_SLINEAR;
  64. /* datalen will vary for each frame */
  65. tmp->fr.src = name;
  66. tmp->fr.mallocd = 0;
  67. glistcnt++;
  68. ast_mutex_unlock(&slinear_lock);
  69. ast_update_use_count();
  70. }
  71. return tmp;
  72. }
  73. static struct ast_filestream *slinear_rewrite(int fd, char *comment)
  74. {
  75. /* We don't have any header to read or anything really, but
  76. if we did, it would go here. We also might want to check
  77. and be sure it's a valid file. */
  78. struct ast_filestream *tmp;
  79. if ((tmp = malloc(sizeof(struct ast_filestream)))) {
  80. memset(tmp, 0, sizeof(struct ast_filestream));
  81. if (ast_mutex_lock(&slinear_lock)) {
  82. ast_log(LOG_WARNING, "Unable to lock slinear list\n");
  83. free(tmp);
  84. return NULL;
  85. }
  86. tmp->fd = fd;
  87. glistcnt++;
  88. ast_mutex_unlock(&slinear_lock);
  89. ast_update_use_count();
  90. } else
  91. ast_log(LOG_WARNING, "Out of memory\n");
  92. return tmp;
  93. }
  94. static void slinear_close(struct ast_filestream *s)
  95. {
  96. if (ast_mutex_lock(&slinear_lock)) {
  97. ast_log(LOG_WARNING, "Unable to lock slinear list\n");
  98. return;
  99. }
  100. glistcnt--;
  101. ast_mutex_unlock(&slinear_lock);
  102. ast_update_use_count();
  103. close(s->fd);
  104. free(s);
  105. s = NULL;
  106. }
  107. static struct ast_frame *slinear_read(struct ast_filestream *s, int *whennext)
  108. {
  109. int res;
  110. int delay;
  111. /* Send a frame from the file to the appropriate channel */
  112. s->fr.frametype = AST_FRAME_VOICE;
  113. s->fr.subclass = AST_FORMAT_SLINEAR;
  114. s->fr.offset = AST_FRIENDLY_OFFSET;
  115. s->fr.mallocd = 0;
  116. s->fr.data = s->buf;
  117. if ((res = read(s->fd, s->buf, BUF_SIZE)) < 1) {
  118. if (res)
  119. ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
  120. return NULL;
  121. }
  122. s->fr.samples = res/2;
  123. s->fr.datalen = res;
  124. delay = s->fr.samples;
  125. *whennext = delay;
  126. return &s->fr;
  127. }
  128. static int slinear_write(struct ast_filestream *fs, struct ast_frame *f)
  129. {
  130. int res;
  131. if (f->frametype != AST_FRAME_VOICE) {
  132. ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
  133. return -1;
  134. }
  135. if (f->subclass != AST_FORMAT_SLINEAR) {
  136. ast_log(LOG_WARNING, "Asked to write non-slinear frame (%d)!\n", f->subclass);
  137. return -1;
  138. }
  139. if ((res = write(fs->fd, f->data, f->datalen)) != f->datalen) {
  140. ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n", res, f->datalen, strerror(errno));
  141. return -1;
  142. }
  143. return 0;
  144. }
  145. static int slinear_seek(struct ast_filestream *fs, long sample_offset, int whence)
  146. {
  147. off_t offset=0,min,cur,max;
  148. min = 0;
  149. sample_offset <<= 1;
  150. cur = lseek(fs->fd, 0, SEEK_CUR);
  151. max = lseek(fs->fd, 0, SEEK_END);
  152. if (whence == SEEK_SET)
  153. offset = sample_offset;
  154. else if (whence == SEEK_CUR || whence == SEEK_FORCECUR)
  155. offset = sample_offset + cur;
  156. else if (whence == SEEK_END)
  157. offset = max - sample_offset;
  158. if (whence != SEEK_FORCECUR) {
  159. offset = (offset > max)?max:offset;
  160. }
  161. // always protect against seeking past begining.
  162. offset = (offset < min)?min:offset;
  163. return lseek(fs->fd, offset, SEEK_SET);
  164. }
  165. static int slinear_trunc(struct ast_filestream *fs)
  166. {
  167. return ftruncate(fs->fd, lseek(fs->fd,0,SEEK_CUR));
  168. }
  169. static long slinear_tell(struct ast_filestream *fs)
  170. {
  171. off_t offset;
  172. offset = lseek(fs->fd, 0, SEEK_CUR);
  173. return offset;
  174. }
  175. static char *slinear_getcomment(struct ast_filestream *s)
  176. {
  177. return NULL;
  178. }
  179. int load_module()
  180. {
  181. return ast_format_register(name, exts, AST_FORMAT_SLINEAR,
  182. slinear_open,
  183. slinear_rewrite,
  184. slinear_write,
  185. slinear_seek,
  186. slinear_trunc,
  187. slinear_tell,
  188. slinear_read,
  189. slinear_close,
  190. slinear_getcomment);
  191. }
  192. int unload_module()
  193. {
  194. return ast_format_unregister(name);
  195. }
  196. int usecount()
  197. {
  198. int res;
  199. if (ast_mutex_lock(&slinear_lock)) {
  200. ast_log(LOG_WARNING, "Unable to lock slinear list\n");
  201. return -1;
  202. }
  203. res = glistcnt;
  204. ast_mutex_unlock(&slinear_lock);
  205. return res;
  206. }
  207. char *description()
  208. {
  209. return desc;
  210. }
  211. char *key()
  212. {
  213. return ASTERISK_GPL_KEY;
  214. }