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