1
/********************************************************************************
3
* this file is part of: *
4
* libeep, the project for reading and writing avr/cnt eeg and related files *
6
********************************************************************************
8
* LICENSE:Copyright (c) 2003-2009, *
9
* Advanced Neuro Technology (ANT) B.V., Enschede, The Netherlands *
10
* Max-Planck Institute for Human Cognitive & Brain Sciences, Leipzig, Germany *
12
********************************************************************************
14
* This library is free software; you can redistribute it and/or modify *
15
* it under the terms of the GNU Lesser General Public License as published by *
16
* the Free Software Foundation; either version 3 of the License, or *
17
* (at your option) any later version. *
19
* This library is distributed WITHOUT ANY WARRANTY; even the implied warranty *
20
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
21
* GNU Lesser General Public License for more details. *
23
* You should have received a copy of the GNU Lesser General Public License *
24
* along with this program. If not, see <http://www.gnu.org/licenses/> *
26
*******************************************************************************/
29
#include <eep/eepraw.h>
32
char RCS_riff_h[] = RCS_RIFF_H;
33
char RCS_riff_c[] = "$RCSfile: riff.c,v $ $Revision: 2415 $";
46
#define CHUNKHEADER_SIZE 8
47
#define PARENTHEADER_SIZE 12
50
int get_id(FILE *f, fourcc_t *in)
55
*in = FOURCC(id[0], id[1], id[2], id[3]);
60
int put_id(FILE *f, fourcc_t out)
64
id[0] = (char) (out & 0xff);
65
id[1] = (char) ((out >> 8) & 0xff);
66
id[2] = (char) ((out >> 16) & 0xff);
67
id[3] = (char) ((out >> 24) & 0xff);
74
int get_chunk(FILE *f, chunk_t *in)
78
read_s32(f, &(in->size));
83
int put_chunk(FILE *f, chunk_t out)
86
write_u32(f, out.size);
91
int riff_form_open(FILE *f, chunk_t *chunk, fourcc_t *formtype)
97
if (chunk->id == FOURCC_RIFF) {
102
return RIFFERR_NOCHUNK;
106
int riff_list_open(FILE *f, chunk_t *chunk, fourcc_t listtype, chunk_t parent)
108
fourcc_t curlisttype;
113
/* locate the start of our tree level (the parents data area) */
115
fseek(f, parent.start + PARENTHEADER_SIZE, SEEK_SET);
117
fseek(f, nextchunk, SEEK_CUR);
118
if (get_chunk(f, chunk)) return RIFFERR_FILE;
119
if (chunk->id == FOURCC_LIST) {
120
get_id(f, &curlisttype);
121
if (curlisttype == listtype) {
125
skipsize += chunk->size + CHUNKHEADER_SIZE + (chunk->size & 0x01);
126
nextchunk = chunk->size - 4 + (chunk->size & 0x01);
130
skipsize += chunk->size + CHUNKHEADER_SIZE + (chunk->size & 0x01);
131
nextchunk = chunk->size + (chunk->size & 0x01);
133
} while (!match && skipsize < parent.size - 1);
138
return RIFFERR_NOCHUNK;
142
int riff_open(FILE *f, chunk_t *chunk, fourcc_t id, chunk_t parent)
148
/* go to parent data area */
149
fseek(f, parent.start + PARENTHEADER_SIZE, SEEK_SET);
151
/* loop true the childs on this level, no recursion into tree! */
153
fseek(f, nextchunk, SEEK_CUR);
154
if (get_chunk(f, chunk)) return RIFFERR_FILE;
155
// printf("%8lX\t%8lX\t%8lX\n", chunk->id, chunk->size, ftell(f)-8);
156
if (chunk->id == id) {
160
skipsize += chunk->size + CHUNKHEADER_SIZE + (chunk->size & 0x01);
161
nextchunk = chunk->size + (chunk->size & 0x01);
163
} while (!match && skipsize < parent.size);
168
return RIFFERR_NOCHUNK;
173
int riff_fetch(FILE *f, chunk_t *chunk, fourcc_t *listid,
174
chunk_t parent, int child)
179
/* locate parent data area start */
180
fseek(f, parent.start + PARENTHEADER_SIZE, SEEK_SET);
182
s = get_chunk(f, chunk);
183
while (!s && i != child && got + chunk->size < parent.size)
185
fseek(f, chunk->size + (chunk->size & 1), SEEK_CUR);
186
got += CHUNKHEADER_SIZE + chunk->size + (chunk->size & 1);
187
s = get_chunk(f, chunk);
191
if (s || got + chunk->size > parent.size) {
192
return RIFFERR_NOCHUNK;
195
if (chunk->id == FOURCC_LIST)
201
int riff_form_new(FILE *f, chunk_t *chunk, fourcc_t formtype)
205
chunk->id = FOURCC_RIFF;
206
chunk->parent = NULL;
210
if (put_chunk(f, *chunk)) return RIFFERR_FILE;
211
if (put_id(f, formtype)) return RIFFERR_FILE;
217
int riff_list_new(FILE *f, chunk_t *chunk, fourcc_t listtype, chunk_t *parent)
221
chunk->id = FOURCC_LIST;
222
chunk->start = ftell(f);
224
chunk->parent = parent;
227
if (put_chunk(f, *chunk)) return RIFFERR_FILE;
228
if (put_id(f, listtype)) return RIFFERR_FILE;
231
while (x->parent != NULL) {
233
x->size += PARENTHEADER_SIZE;
240
int riff_new(FILE *f, chunk_t *chunk, fourcc_t chunktype, chunk_t *parent)
244
/*fseek(f, 0, SEEK_END);*/
246
chunk->id = chunktype;
247
chunk->start = ftell(f);
248
chunk->parent = parent;
251
if (put_chunk(f, *chunk)) return RIFFERR_FILE;
253
while (x->parent != NULL) {
255
x->size += CHUNKHEADER_SIZE;
261
int riff_close(FILE *f, chunk_t chunk)
268
/*fseek(f, 0, SEEK_END);*/
270
fillbytes = start & 0x01;
272
/* write the chunk header */
273
fseek(f, chunk.start, SEEK_SET);
274
if (put_chunk(f, chunk)) return RIFFERR_FILE;
276
/* tell the parents about their new size */
278
while (x->parent != NULL) {
280
x->size += fillbytes + chunk.size;
281
fseek(f, x->start, SEEK_SET);
282
if (put_chunk(f, *x)) return RIFFERR_FILE;
285
/* force next start at even filepos */
286
/*fseek(f, 0, SEEK_END); Next line will be equivalent in case of seek_end == true */
287
fseek(f, start, SEEK_SET);
288
if (fillbytes) fwrite(&junk, 1, 1, f);
293
int riff_write(const char *buf, size_t size, size_t num_items,
294
FILE *f, chunk_t *chunk)
296
long sizeinc = size * num_items;
297
if (fwrite(buf, size, num_items, f) != num_items) return RIFFERR_FILE;
298
chunk->size += sizeinc;
303
int riff_read(char *buf, size_t size, size_t num_items,
304
FILE *f, chunk_t chunk)
306
if (fread(buf, size, num_items, f) != num_items) return RIFFERR_FILE;
311
int riff_seek(FILE *f, long offset, int whence, chunk_t chunk)
316
case SEEK_SET: effpos = chunk.start + CHUNKHEADER_SIZE + offset;
318
case SEEK_CUR: effpos = offset;
320
case SEEK_END: effpos = chunk.start + CHUNKHEADER_SIZE + chunk.size;
323
if (fseek(f, effpos, (whence != SEEK_CUR) ? SEEK_SET : SEEK_CUR))
329
long get_chunk_size(chunk_t chunk)
333
fourcc_t get_chunk_id(chunk_t chunk)