File: iff.c

package info (click to toggle)
xmp 3.4.0-1.1
  • links: PTS
  • area: main
  • in suites: wheezy
  • size: 4,212 kB
  • sloc: ansic: 47,206; sh: 2,933; asm: 1,013; makefile: 397; xml: 47; cpp: 40
file content (122 lines) | stat: -rw-r--r-- 2,299 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/* Extended Module Player
 * Copyright (C) 1997-2010 Claudio Matsuoka and Hipolito Carraro Jr
 *
 * This file is part of the Extended Module Player and is distributed
 * under the terms of the GNU General Public License. See doc/COPYING
 * for more information.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "common.h"
#include "list.h"
#include "iff.h"

#include "load.h"

static LIST_HEAD(iff_list);

static int __id_size;
static int __flags;

void iff_chunk(struct xmp_context *ctx, FILE *f)
{
    long size;
    char id[17] = "";

    if (fread(id, 1, __id_size, f) != __id_size)
	return;

    if (__flags & IFF_SKIP_EMBEDDED) {
	/* embedded RIFF hack */
	if (!strncmp(id, "RIFF", 4)) {
	    read32b(f);
	    read32b(f);
	    fread(id, 1, __id_size, f);	/* read first chunk ID instead */
        }
    }

    size = (__flags & IFF_LITTLE_ENDIAN) ? read32l(f) : read32b(f);

    if (__flags & IFF_CHUNK_ALIGN2)
	size = (size + 1) & ~1;

    if (__flags & IFF_CHUNK_ALIGN4)
	size = (size + 3) & ~3;

    if (__flags & IFF_FULL_CHUNK_SIZE)
	size -= __id_size + 4;

    iff_process(ctx, id, size, f);
}


void iff_register(char *id, void (*loader)(struct xmp_context *, int, FILE *))
{
    struct iff_info *f;

    __id_size = 4;
    __flags = 0;

    f = malloc(sizeof (struct iff_info));
    strcpy(f->id, id);
    f->loader = loader;

    list_add_tail(&f->list, &iff_list);
}


void iff_release()
{
    struct list_head *tmp;
    struct iff_info *i;

    /* can't use list_for_each because we free the node before incrementing */
    for (tmp = (&iff_list)->next; tmp != (&iff_list); ) {
	i = list_entry(tmp, struct iff_info, list);
	list_del(&i->list);
	tmp = tmp->next;
	free(i);
    }
}


int iff_process(struct xmp_context *ctx, char *id, long size, FILE *f)
{
    struct list_head *tmp;
    struct iff_info *i;
    int pos;

    pos = ftell(f);

    list_for_each(tmp, &iff_list) {
	i = list_entry(tmp, struct iff_info, list);
	if (id && !strncmp(id, i->id, __id_size)) {
	    i->loader(ctx, size, f);
	    break;
	}
    }

    fseek(f, pos + size, SEEK_SET);

    return 0;
}


/* Functions to tune IFF mutations */

void iff_idsize (int n)
{
    __id_size = n;
}

void iff_setflag (int i)
{
    __flags |= i;
}