~ubuntu-branches/ubuntu/precise/openwalnut/precise

« back to all changes in this revision

Viewing changes to src/modules/data/ext/libeep/libcnt/riff.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Eichelbaum
  • Date: 2011-06-21 10:26:54 UTC
  • Revision ID: james.westby@ubuntu.com-20110621102654-rq0zf436q949biih
Tags: upstream-1.2.5
ImportĀ upstreamĀ versionĀ 1.2.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/********************************************************************************
 
2
 *                                                                              *
 
3
 * this file is part of:                                                        *
 
4
 * libeep, the project for reading and writing avr/cnt eeg and related files    *
 
5
 *                                                                              *
 
6
 ********************************************************************************
 
7
 *                                                                              *
 
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  *
 
11
 *                                                                              *
 
12
 ********************************************************************************
 
13
 *                                                                              *
 
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.                                          *
 
18
 *                                                                              *
 
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.                          *
 
22
 *                                                                              *
 
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/>          *
 
25
 *                                                                              *
 
26
 *******************************************************************************/
 
27
 
 
28
#include <cnt/riff.h>
 
29
#include <eep/eepraw.h>
 
30
 
 
31
#ifdef COMPILE_RCS
 
32
char RCS_riff_h[] = RCS_RIFF_H;
 
33
char RCS_riff_c[] = "$RCSfile: riff.c,v $ $Revision: 2415 $";
 
34
#endif
 
35
 
 
36
#ifndef SEEK_SET
 
37
# define SEEK_SET 0
 
38
#endif
 
39
#ifndef SEEK_CUR
 
40
# define SEEK_CUR 1
 
41
#endif
 
42
#ifndef SEEK_END
 
43
# define SEEK_END 2
 
44
#endif
 
45
 
 
46
#define CHUNKHEADER_SIZE 8
 
47
#define PARENTHEADER_SIZE 12
 
48
 
 
49
 
 
50
int get_id(FILE *f, fourcc_t *in)
 
51
{
 
52
  char id[4];
 
53
 
 
54
  fread(id, 4, 1, f);
 
55
  *in = FOURCC(id[0], id[1], id[2], id[3]);
 
56
 
 
57
  return ferror(f);
 
58
}
 
59
 
 
60
int put_id(FILE *f, fourcc_t out)
 
61
{
 
62
  char id[4];
 
63
 
 
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);
 
68
 
 
69
  fwrite(id, 4, 1, f);
 
70
 
 
71
  return ferror(f);
 
72
}
 
73
 
 
74
int get_chunk(FILE *f, chunk_t *in)
 
75
{
 
76
  in->start = ftell(f);
 
77
  get_id(f, &(in->id));
 
78
  read_s32(f, &(in->size));
 
79
 
 
80
  return ferror(f);
 
81
}
 
82
 
 
83
int put_chunk(FILE *f, chunk_t out)
 
84
{
 
85
  put_id(f, out.id);
 
86
  write_u32(f, out.size);
 
87
 
 
88
  return ferror(f);
 
89
}
 
90
 
 
91
int riff_form_open(FILE *f, chunk_t *chunk, fourcc_t *formtype)
 
92
{
 
93
  rewind(f);
 
94
 
 
95
  chunk->parent = NULL;
 
96
  get_chunk(f, chunk);
 
97
  if (chunk->id == FOURCC_RIFF) {
 
98
    get_id(f, formtype);
 
99
    return RIFFERR_NONE;
 
100
  }
 
101
  else {
 
102
    return RIFFERR_NOCHUNK;
 
103
  }
 
104
}
 
105
 
 
106
int riff_list_open(FILE *f, chunk_t *chunk, fourcc_t listtype, chunk_t parent)
 
107
{
 
108
  fourcc_t curlisttype;
 
109
  char match = 0;
 
110
  long nextchunk = 0;
 
111
  long skipsize = 0;
 
112
  
 
113
  /* locate the start of our tree level (the parents data area) */
 
114
 
 
115
  fseek(f, parent.start + PARENTHEADER_SIZE, SEEK_SET);
 
116
  do {
 
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) {
 
122
        match = 1;
 
123
      }
 
124
      else {
 
125
        skipsize += chunk->size + CHUNKHEADER_SIZE + (chunk->size & 0x01);
 
126
        nextchunk = chunk->size - 4 + (chunk->size & 0x01);
 
127
      }
 
128
    }
 
129
    else {
 
130
      skipsize += chunk->size + CHUNKHEADER_SIZE + (chunk->size & 0x01);
 
131
      nextchunk = chunk->size + (chunk->size & 0x01);
 
132
    }
 
133
  } while (!match && skipsize < parent.size - 1);
 
134
  
 
135
  if (match)
 
136
    return RIFFERR_NONE;
 
137
  else
 
138
    return RIFFERR_NOCHUNK;
 
139
  
 
140
}
 
141
 
 
142
int riff_open(FILE *f, chunk_t *chunk, fourcc_t id, chunk_t parent)
 
143
{
 
144
  char match = 0;
 
145
  long nextchunk = 0;
 
146
  long skipsize = 0;
 
147
  
 
148
  /* go to parent data area */
 
149
  fseek(f, parent.start + PARENTHEADER_SIZE, SEEK_SET);
 
150
  
 
151
  /* loop true the childs on this level, no recursion into tree! */
 
152
  do {
 
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) {
 
157
      match = 1;
 
158
    }
 
159
    else {
 
160
      skipsize += chunk->size + CHUNKHEADER_SIZE + (chunk->size & 0x01);
 
161
      nextchunk = chunk->size + (chunk->size & 0x01);
 
162
    }
 
163
  } while (!match && skipsize < parent.size);
 
164
 
 
165
  if (match) {
 
166
    return RIFFERR_NONE;
 
167
  } else {
 
168
    return RIFFERR_NOCHUNK;
 
169
  }
 
170
 
 
171
}
 
172
 
 
173
int riff_fetch(FILE *f, chunk_t *chunk, fourcc_t *listid, 
 
174
               chunk_t parent, int child)
 
175
{
 
176
  int s, i = 0;
 
177
  long got = 0;
 
178
  
 
179
  /* locate parent data area start */
 
180
  fseek(f, parent.start + PARENTHEADER_SIZE, SEEK_SET);
 
181
  
 
182
  s = get_chunk(f, chunk);
 
183
  while (!s && i != child && got + chunk->size < parent.size)
 
184
  {
 
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);
 
188
    i++;
 
189
  }
 
190
  
 
191
  if (s || got + chunk->size > parent.size) {
 
192
    return RIFFERR_NOCHUNK;
 
193
  }
 
194
  else {
 
195
    if (chunk->id == FOURCC_LIST)
 
196
      get_id(f, listid);
 
197
    return RIFFERR_NONE;
 
198
  }
 
199
}
 
200
 
 
201
int riff_form_new(FILE *f, chunk_t *chunk, fourcc_t formtype)
 
202
{
 
203
  rewind(f);
 
204
  
 
205
  chunk->id = FOURCC_RIFF;
 
206
  chunk->parent = NULL;
 
207
  chunk->start = 0;
 
208
  chunk->size = 4;
 
209
 
 
210
  if (put_chunk(f, *chunk)) return RIFFERR_FILE;
 
211
  if (put_id(f, formtype)) return RIFFERR_FILE;
 
212
 
 
213
  return RIFFERR_NONE;
 
214
}
 
215
 
 
216
 
 
217
int riff_list_new(FILE *f, chunk_t *chunk, fourcc_t listtype, chunk_t *parent)
 
218
{
 
219
  chunk_t *x;
 
220
 
 
221
  chunk->id = FOURCC_LIST;
 
222
  chunk->start = ftell(f);
 
223
  chunk->size = 4;
 
224
  chunk->parent = parent;
 
225
 
 
226
 
 
227
  if (put_chunk(f, *chunk)) return RIFFERR_FILE;
 
228
  if (put_id(f, listtype)) return RIFFERR_FILE;
 
229
 
 
230
  x = chunk;
 
231
  while (x->parent != NULL) {
 
232
    x = x->parent;
 
233
    x->size += PARENTHEADER_SIZE;
 
234
  }
 
235
 
 
236
  return RIFFERR_NONE;
 
237
}
 
238
 
 
239
 
 
240
int riff_new(FILE *f, chunk_t *chunk, fourcc_t chunktype, chunk_t *parent)
 
241
{
 
242
  chunk_t *x;
 
243
 
 
244
  /*fseek(f, 0, SEEK_END);*/
 
245
 
 
246
  chunk->id = chunktype;
 
247
  chunk->start = ftell(f);
 
248
  chunk->parent = parent;
 
249
  chunk->size = 0;
 
250
 
 
251
  if (put_chunk(f, *chunk)) return RIFFERR_FILE;
 
252
  x = chunk;
 
253
  while (x->parent != NULL) {
 
254
    x = x->parent;
 
255
    x->size += CHUNKHEADER_SIZE;
 
256
  }
 
257
 
 
258
  return ferror(f);
 
259
}
 
260
 
 
261
int riff_close(FILE *f, chunk_t chunk)
 
262
{
 
263
  long fillbytes;
 
264
  long start;
 
265
  chunk_t *x;
 
266
  char junk = '\0';
 
267
 
 
268
  /*fseek(f, 0, SEEK_END);*/
 
269
  start = ftell(f);
 
270
  fillbytes = start & 0x01;
 
271
 
 
272
  /* write the chunk header */
 
273
  fseek(f, chunk.start, SEEK_SET);
 
274
  if (put_chunk(f, chunk)) return RIFFERR_FILE;
 
275
 
 
276
  /* tell the parents about their new size */
 
277
  x = &chunk;
 
278
  while (x->parent != NULL) {
 
279
    x = x->parent;
 
280
    x->size += fillbytes + chunk.size;
 
281
    fseek(f, x->start, SEEK_SET);
 
282
    if (put_chunk(f, *x)) return RIFFERR_FILE;
 
283
  }
 
284
 
 
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);
 
289
 
 
290
  return RIFFERR_NONE;
 
291
}
 
292
 
 
293
int riff_write(const char *buf, size_t size, size_t num_items,
 
294
               FILE *f, chunk_t *chunk)
 
295
{
 
296
  long sizeinc = size * num_items;
 
297
  if (fwrite(buf, size, num_items, f) != num_items) return RIFFERR_FILE;
 
298
  chunk->size += sizeinc;
 
299
 
 
300
  return RIFFERR_NONE;
 
301
}
 
302
 
 
303
int riff_read(char *buf, size_t size, size_t num_items, 
 
304
                    FILE *f, chunk_t chunk)
 
305
{
 
306
  if (fread(buf, size, num_items, f) != num_items) return RIFFERR_FILE;
 
307
  
 
308
  return RIFFERR_NONE;
 
309
}
 
310
 
 
311
int riff_seek(FILE *f, long offset, int whence, chunk_t chunk)
 
312
{
 
313
  long effpos=0;
 
314
  
 
315
  switch (whence) {
 
316
    case SEEK_SET: effpos = chunk.start + CHUNKHEADER_SIZE + offset;
 
317
                   break;
 
318
    case SEEK_CUR: effpos = offset;
 
319
                   break;
 
320
    case SEEK_END: effpos = chunk.start + CHUNKHEADER_SIZE + chunk.size;
 
321
                   break;
 
322
  }
 
323
  if (fseek(f, effpos, (whence != SEEK_CUR) ? SEEK_SET : SEEK_CUR))
 
324
    return RIFFERR_FILE;
 
325
  else
 
326
    return RIFFERR_NONE;
 
327
}
 
328
 
 
329
long get_chunk_size(chunk_t chunk)
 
330
{
 
331
  return chunk.size;
 
332
}
 
333
fourcc_t get_chunk_id(chunk_t chunk)
 
334
{
 
335
  return chunk.id;
 
336
}