1 #include <assert.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4
5 #ifdef HAVE_CONFIG_H
6 #include <config.h>
7 #endif /* HAVE_CONFIG_H */
8 #include <simage.h>
9 #include <simage_private.h>
10 #include <string.h>
11
12 #ifdef SIMAGE_OGGVORBIS_SUPPORT
13 #include "simage_oggvorbis.h"
14 #endif /* SIMAGE_OGGVORBIS_SUPPORT */
15
16 #ifdef SIMAGE_LIBSNDFILE_SUPPORT
17 #include "simage_libsndfile.h"
18 #endif /* SIMAGE_LIBSNDFILE_SUPPORT */
19
20 struct simage_stream_s {
21 char * filename;
22
23 s_stream_open_func * open;
24 s_stream_create_func * create;
25 s_stream_get_func * get;
26 s_stream_put_func * put;
27 s_stream_close_func * close;
28 s_stream_seek_func * seek;
29 s_stream_tell_func * tell;
30
31 s_params * params;
32 void *context;
33 };
34
35 struct simage_stream_importer {
36 s_stream_open_func * open;
37 s_stream_get_func * get;
38 s_stream_seek_func * seek;
39 s_stream_tell_func * tell;
40 s_stream_close_func * close;
41
42 struct simage_stream_importer * next;
43 };
44
45 struct simage_stream_exporter {
46 s_stream_create_func * create;
47 s_stream_put_func * put;
48 s_stream_seek_func * seek;
49 s_stream_tell_func * tell;
50 s_stream_close_func * close;
51
52 struct simage_stream_exporter * next;
53 };
54
55 // FIXME: convert access to these variables into the singleton
56 // pattern. 20010917 mortene.
57 static struct simage_stream_importer * importers;
58 static struct simage_stream_exporter * exporters;
59
60 static void
add_internal_importers(void)61 add_internal_importers(void)
62 {
63 static int first = 1;
64 if (first) {
65 #ifdef SIMAGE_OGGVORBIS_SUPPORT
66 s_stream_importer_add_ex(oggvorbis_reader_stream_open,
67 oggvorbis_reader_stream_get,
68 oggvorbis_reader_stream_seek,
69 oggvorbis_reader_stream_tell,
70 oggvorbis_reader_stream_close);
71 #endif
72 #ifdef SIMAGE_LIBSNDFILE_SUPPORT
73 s_stream_importer_add_ex(libsndfile_stream_open,
74 libsndfile_stream_get,
75 libsndfile_stream_seek,
76 libsndfile_stream_tell,
77 libsndfile_stream_close);
78 #endif
79 first = 0;
80 }
81 }
82
83 static void
add_internal_exporters(void)84 add_internal_exporters(void)
85 {
86 static int first = 1;
87 if (first) {
88 /* none yet */
89 first = 0;
90 }
91 }
92
93 s_stream *
s_stream_open(const char * filename,s_params * params)94 s_stream_open(const char * filename, s_params * params)
95 {
96 struct simage_stream_importer * imp;
97 s_stream * stream;
98
99 stream = (s_stream*) malloc(sizeof(s_stream));
100 stream->params = NULL;
101 stream->filename = NULL;
102 stream->context = NULL;
103
104 add_internal_importers();
105
106 imp = importers;
107 while (imp) {
108 if (imp->open(filename, stream, params)) break;
109 imp = imp->next;
110 }
111 if (imp == NULL) {
112 free((void*)stream);
113 return NULL;
114 }
115
116 stream->filename = (char*) malloc(strlen(filename)+1);
117 strcpy(stream->filename, filename);
118 stream->open = imp->open;
119 stream->get = imp->get;
120 stream->close = imp->close;
121 stream->seek = imp->seek;
122 stream->tell = imp->tell;
123
124 return stream;
125 }
126
127 s_stream *
s_stream_create(const char * filename,s_params * params)128 s_stream_create(const char * filename, s_params * params /* | NULL */)
129 {
130 struct simage_stream_exporter * exp;
131 s_stream * stream = (s_stream*) malloc(sizeof(s_stream));
132 stream->params = NULL;
133 stream->filename = NULL;
134 stream->context = NULL;
135
136 add_internal_exporters();
137
138 exp = exporters;
139 while (exp) {
140 if (exp->create(filename, stream, params)) break;
141 exp = exp->next;
142 }
143 if (exp == NULL) {
144 free((void*) stream);
145 return NULL;
146 }
147
148 stream->filename = (char*) malloc(strlen(filename)+1);
149 stream->create = exp->create;
150 stream->put = exp->put;
151 stream->close = exp->close;
152 stream->seek = exp->seek;
153 stream->tell = exp->tell;
154 strcpy(stream->filename, filename);
155 return stream;
156 }
157
158 void *
s_stream_get_buffer(s_stream * stream,void * buffer,int * size,s_params * params)159 s_stream_get_buffer(s_stream * stream, void * buffer,
160 int *size, s_params * params)
161 {
162 return stream->get(stream, buffer, size, params);
163 }
164
165 int
s_stream_put_buffer(s_stream * stream,void * buffer,int size,s_params * params)166 s_stream_put_buffer(s_stream * stream, void * buffer,
167 int size, s_params * params)
168 {
169 return stream->put(stream, buffer, size, params);
170 }
171
172 void
s_stream_close(s_stream * stream)173 s_stream_close(s_stream * stream)
174 {
175 stream->close(stream);
176 }
177
178 void
s_stream_destroy(s_stream * stream)179 s_stream_destroy(s_stream * stream)
180 {
181 if (stream->params) s_params_destroy(stream->params);
182 if (stream->filename) free((void*) stream->filename);
183 free((void*) stream);
184 }
185
186 s_params *
s_stream_params(s_stream * stream)187 s_stream_params(s_stream * stream)
188 {
189 if (stream->params == NULL) {
190 stream->params = s_params_create();
191 }
192 return stream->params;
193 }
194
195 void *
s_stream_context_get(s_stream * stream)196 s_stream_context_get(s_stream *stream)
197 {
198 return stream->context;
199 }
200
201 void
s_stream_context_set(s_stream * stream,void * context)202 s_stream_context_set(s_stream *stream, void *context)
203 {
204 stream->context = context;
205 }
206
207 void
s_stream_importer_add(s_stream_open_func * open,s_stream_get_func * get,s_stream_close_func * close)208 s_stream_importer_add(s_stream_open_func * open,
209 s_stream_get_func * get,
210 s_stream_close_func * close)
211 {
212 s_stream_importer_add_ex(open, get, NULL, NULL, close);
213 }
214
215 void
s_stream_importer_add_ex(s_stream_open_func * open,s_stream_get_func * get,s_stream_seek_func * seek,s_stream_tell_func * tell,s_stream_close_func * close)216 s_stream_importer_add_ex(s_stream_open_func * open,
217 s_stream_get_func * get,
218 s_stream_seek_func * seek,
219 s_stream_tell_func * tell,
220 s_stream_close_func * close)
221 {
222 struct simage_stream_importer * last, * imp = importers;
223 last = NULL;
224 while (imp) {
225 last = imp;
226 imp = imp->next;
227 }
228 imp = (struct simage_stream_importer*) malloc(sizeof(struct simage_stream_importer));
229 imp->open = open;
230 imp->get = get;
231 imp->close = close;
232 imp->seek = seek;
233 imp->tell = tell;
234 imp->next = NULL;
235
236 if (last == NULL) {
237 importers = imp;
238 }
239 else last->next = imp;
240 }
241
242 void
s_stream_exporter_add(s_stream_create_func * create,s_stream_put_func * put,s_stream_close_func * close)243 s_stream_exporter_add(s_stream_create_func * create,
244 s_stream_put_func * put,
245 s_stream_close_func * close)
246 {
247 s_stream_exporter_add_ex(create, put, NULL, NULL, close);
248 }
249
250 void
s_stream_exporter_add_ex(s_stream_create_func * create,s_stream_put_func * put,s_stream_seek_func * seek,s_stream_tell_func * tell,s_stream_close_func * close)251 s_stream_exporter_add_ex(s_stream_create_func * create,
252 s_stream_put_func * put,
253 s_stream_seek_func * seek,
254 s_stream_tell_func * tell,
255 s_stream_close_func * close)
256 {
257 struct simage_stream_exporter * last, * exp = exporters;
258 last = NULL;
259 while (exp) {
260 last = exp;
261 exp = exp->next;
262 }
263 exp = (struct simage_stream_exporter*) malloc(sizeof(struct simage_stream_exporter));
264 exp->create = create;
265 exp->put = put;
266 exp->close = close;
267 exp->seek = seek;
268 exp->tell = tell;
269 exp->next = NULL;
270
271 if (last == NULL) {
272 exporters = exp;
273 }
274 else last->next = exp;
275 }
276
277 int
s_stream_seek(s_stream * stream,int offset,int whence,s_params * params)278 s_stream_seek(s_stream * stream, int offset, int whence,
279 s_params * params /* | NULL */)
280 {
281 if (stream->seek)
282 return stream->seek(stream, offset, whence, params);
283 else
284 return -1;
285 }
286
s_stream_tell(s_stream * stream,s_params * params)287 int s_stream_tell(s_stream *stream,
288 s_params * params /* | NULL */)
289 {
290 if (stream->tell)
291 return stream->tell(stream, params);
292 else
293 return -1;
294 }
295