format_sln.c 5.5 KB

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