Asterisk media architecture conversion - no more format bitfields
[asterisk/asterisk.git] / formats / format_sln.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Anthony Minessale
5  * Anthony Minessale (anthmct@yahoo.com)
6  *
7  * See http://www.asterisk.org for more information about
8  * the Asterisk project. Please do not directly contact
9  * any of the maintainers of this project for assistance;
10  * the project provides a web site, mailing lists and IRC
11  * channels for your use.
12  *
13  * This program is free software, distributed under the terms of
14  * the GNU General Public License Version 2. See the LICENSE file
15  * at the top of the source tree.
16  */
17
18 /*! \file
19  *
20  * \brief RAW SLINEAR Format
21  * \arg File name extensions: sln, raw
22  * \ingroup formats
23  */
24  
25 #include "asterisk.h"
26
27 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
28
29 #include "asterisk/mod_format.h"
30 #include "asterisk/module.h"
31 #include "asterisk/endian.h"
32
33 #define BUF_SIZE        320             /* 320 bytes, 160 samples */
34 #define SLIN_SAMPLES    160
35
36 static struct ast_frame *slinear_read(struct ast_filestream *s, int *whennext)
37 {
38         int res;
39         /* Send a frame from the file to the appropriate channel */
40
41         s->fr.frametype = AST_FRAME_VOICE;
42         ast_format_set(&s->fr.subclass.format, AST_FORMAT_SLINEAR, 0);
43         s->fr.mallocd = 0;
44         AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, BUF_SIZE);
45         if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) < 1) {
46                 if (res)
47                         ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno));
48                 return NULL;
49         }
50         *whennext = s->fr.samples = res/2;
51         s->fr.datalen = res;
52         return &s->fr;
53 }
54
55 static int slinear_write(struct ast_filestream *fs, struct ast_frame *f)
56 {
57         int res;
58         if (f->frametype != AST_FRAME_VOICE) {
59                 ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
60                 return -1;
61         }
62         if (f->subclass.format.id != AST_FORMAT_SLINEAR) {
63                 ast_log(LOG_WARNING, "Asked to write non-slinear frame (%s)!\n", ast_getformatname(&f->subclass.format));
64                 return -1;
65         }
66         if ((res = fwrite(f->data.ptr, 1, f->datalen, fs->f)) != f->datalen) {
67                         ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n", res, f->datalen, strerror(errno));
68                         return -1;
69         }
70         return 0;
71 }
72
73 static int slinear_seek(struct ast_filestream *fs, off_t sample_offset, int whence)
74 {
75         off_t offset=0,min,cur,max;
76
77         min = 0;
78         sample_offset <<= 1;
79         cur = ftello(fs->f);
80         fseeko(fs->f, 0, SEEK_END);
81         max = ftello(fs->f);
82         if (whence == SEEK_SET)
83                 offset = sample_offset;
84         else if (whence == SEEK_CUR || whence == SEEK_FORCECUR)
85                 offset = sample_offset + cur;
86         else if (whence == SEEK_END)
87                 offset = max - sample_offset;
88         if (whence != SEEK_FORCECUR) {
89                 offset = (offset > max)?max:offset;
90         }
91         /* always protect against seeking past begining. */
92         offset = (offset < min)?min:offset;
93         return fseeko(fs->f, offset, SEEK_SET);
94 }
95
96 static int slinear_trunc(struct ast_filestream *fs)
97 {
98         return ftruncate(fileno(fs->f), ftello(fs->f));
99 }
100
101 static off_t slinear_tell(struct ast_filestream *fs)
102 {
103         return ftello(fs->f) / 2;
104 }
105
106 static struct ast_format_def slin_f = {
107         .name = "sln",
108         .exts = "sln|raw",
109         .write = slinear_write,
110         .seek = slinear_seek,
111         .trunc = slinear_trunc,
112         .tell = slinear_tell,
113         .read = slinear_read,
114         .buf_size = BUF_SIZE + AST_FRIENDLY_OFFSET,
115 };
116
117 static int load_module(void)
118 {
119         ast_format_set(&slin_f.format, AST_FORMAT_SLINEAR, 0);
120         if (ast_format_def_register(&slin_f))
121                 return AST_MODULE_LOAD_FAILURE;
122         return AST_MODULE_LOAD_SUCCESS;
123 }
124
125 static int unload_module(void)
126 {
127         return ast_format_def_unregister(slin_f.name);
128 }
129
130 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Raw Signed Linear Audio support (SLN)",
131         .load = load_module,
132         .unload = unload_module,
133         .load_pri = AST_MODPRI_APP_DEPEND
134 );