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