00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <unistd.h>
00026 #include <netinet/in.h>
00027 #include <arpa/inet.h>
00028 #include <stdlib.h>
00029 #include <sys/time.h>
00030 #include <stdio.h>
00031 #include <errno.h>
00032 #include <string.h>
00033
00034 #include "asterisk.h"
00035
00036 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 10487 $")
00037
00038 #include "asterisk/lock.h"
00039 #include "asterisk/channel.h"
00040 #include "asterisk/file.h"
00041 #include "asterisk/logger.h"
00042 #include "asterisk/sched.h"
00043 #include "asterisk/module.h"
00044 #include "asterisk/endian.h"
00045
00046 #define BUF_SIZE 320
00047
00048 struct ast_filestream {
00049 void *reserved[AST_RESERVED_POINTERS];
00050
00051 FILE *f;
00052 struct ast_channel *owner;
00053 struct ast_frame fr;
00054 char waste[AST_FRIENDLY_OFFSET];
00055 char empty;
00056 unsigned char buf[BUF_SIZE];
00057 struct timeval last;
00058 };
00059
00060
00061 AST_MUTEX_DEFINE_STATIC(slinear_lock);
00062 static int glistcnt = 0;
00063
00064 static char *name = "sln";
00065 static char *desc = "Raw Signed Linear Audio support (SLN)";
00066 static char *exts = "sln|raw";
00067
00068 static struct ast_filestream *slinear_open(FILE *f)
00069 {
00070
00071
00072
00073 struct ast_filestream *tmp;
00074 if ((tmp = malloc(sizeof(struct ast_filestream)))) {
00075 memset(tmp, 0, sizeof(struct ast_filestream));
00076 if (ast_mutex_lock(&slinear_lock)) {
00077 ast_log(LOG_WARNING, "Unable to lock slinear list\n");
00078 free(tmp);
00079 return NULL;
00080 }
00081 tmp->f = f;
00082 tmp->fr.data = tmp->buf;
00083 tmp->fr.frametype = AST_FRAME_VOICE;
00084 tmp->fr.subclass = AST_FORMAT_SLINEAR;
00085
00086 tmp->fr.src = name;
00087 tmp->fr.mallocd = 0;
00088 glistcnt++;
00089 ast_mutex_unlock(&slinear_lock);
00090 ast_update_use_count();
00091 }
00092 return tmp;
00093 }
00094
00095 static struct ast_filestream *slinear_rewrite(FILE *f, const char *comment)
00096 {
00097
00098
00099
00100 struct ast_filestream *tmp;
00101 if ((tmp = malloc(sizeof(struct ast_filestream)))) {
00102 memset(tmp, 0, sizeof(struct ast_filestream));
00103 if (ast_mutex_lock(&slinear_lock)) {
00104 ast_log(LOG_WARNING, "Unable to lock slinear list\n");
00105 free(tmp);
00106 return NULL;
00107 }
00108 tmp->f = f;
00109 glistcnt++;
00110 ast_mutex_unlock(&slinear_lock);
00111 ast_update_use_count();
00112 } else
00113 ast_log(LOG_WARNING, "Out of memory\n");
00114 return tmp;
00115 }
00116
00117 static void slinear_close(struct ast_filestream *s)
00118 {
00119 if (ast_mutex_lock(&slinear_lock)) {
00120 ast_log(LOG_WARNING, "Unable to lock slinear list\n");
00121 return;
00122 }
00123 glistcnt--;
00124 ast_mutex_unlock(&slinear_lock);
00125 ast_update_use_count();
00126 fclose(s->f);
00127 free(s);
00128 s = NULL;
00129 }
00130
00131 static struct ast_frame *slinear_read(struct ast_filestream *s, int *whennext)
00132 {
00133 int res;
00134 int delay;
00135
00136
00137 s->fr.frametype = AST_FRAME_VOICE;
00138 s->fr.subclass = AST_FORMAT_SLINEAR;
00139 s->fr.offset = AST_FRIENDLY_OFFSET;
00140 s->fr.mallocd = 0;
00141 s->fr.data = s->buf;
00142 if ((res = fread(s->buf, 1, BUF_SIZE, s->f)) < 1) {
00143 if (res)
00144 ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
00145 return NULL;
00146 }
00147 s->fr.samples = res/2;
00148 s->fr.datalen = res;
00149 delay = s->fr.samples;
00150 *whennext = delay;
00151 return &s->fr;
00152 }
00153
00154 static int slinear_write(struct ast_filestream *fs, struct ast_frame *f)
00155 {
00156 int res;
00157 if (f->frametype != AST_FRAME_VOICE) {
00158 ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
00159 return -1;
00160 }
00161 if (f->subclass != AST_FORMAT_SLINEAR) {
00162 ast_log(LOG_WARNING, "Asked to write non-slinear frame (%d)!\n", f->subclass);
00163 return -1;
00164 }
00165 if ((res = fwrite(f->data, 1, f->datalen, fs->f)) != f->datalen) {
00166 ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n", res, f->datalen, strerror(errno));
00167 return -1;
00168 }
00169 return 0;
00170 }
00171
00172 static int slinear_seek(struct ast_filestream *fs, long sample_offset, int whence)
00173 {
00174 off_t offset=0,min,cur,max;
00175
00176 min = 0;
00177 sample_offset <<= 1;
00178 cur = ftell(fs->f);
00179 fseek(fs->f, 0, SEEK_END);
00180 max = ftell(fs->f);
00181 if (whence == SEEK_SET)
00182 offset = sample_offset;
00183 else if (whence == SEEK_CUR || whence == SEEK_FORCECUR)
00184 offset = sample_offset + cur;
00185 else if (whence == SEEK_END)
00186 offset = max - sample_offset;
00187 if (whence != SEEK_FORCECUR) {
00188 offset = (offset > max)?max:offset;
00189 }
00190
00191 offset = (offset < min)?min:offset;
00192 return fseek(fs->f, offset, SEEK_SET);
00193 }
00194
00195 static int slinear_trunc(struct ast_filestream *fs)
00196 {
00197 return ftruncate(fileno(fs->f), ftell(fs->f));
00198 }
00199
00200 static long slinear_tell(struct ast_filestream *fs)
00201 {
00202 off_t offset;
00203 offset = ftell(fs->f);
00204 return offset / 2;
00205 }
00206
00207 static char *slinear_getcomment(struct ast_filestream *s)
00208 {
00209 return NULL;
00210 }
00211
00212 int load_module()
00213 {
00214 return ast_format_register(name, exts, AST_FORMAT_SLINEAR,
00215 slinear_open,
00216 slinear_rewrite,
00217 slinear_write,
00218 slinear_seek,
00219 slinear_trunc,
00220 slinear_tell,
00221 slinear_read,
00222 slinear_close,
00223 slinear_getcomment);
00224
00225
00226 }
00227
00228 int unload_module()
00229 {
00230 return ast_format_unregister(name);
00231 }
00232
00233 int usecount()
00234 {
00235 return glistcnt;
00236 }
00237
00238 char *description()
00239 {
00240 return desc;
00241 }
00242
00243
00244 char *key()
00245 {
00246 return ASTERISK_GPL_KEY;
00247 }