zdoom-macos-deps/deps/instpatch/include/libinstpatch/IpatchRiff.h
2022-09-06 13:49:23 +03:00

195 lines
7.2 KiB
C

/*
* libInstPatch
* Copyright (C) 1999-2014 Element Green <element@elementsofsound.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; version 2.1
* of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA or on the web at http://www.gnu.org.
*/
#ifndef __IPATCH_RIFF_H__
#define __IPATCH_RIFF_H__
#include <glib.h>
#include <libinstpatch/IpatchFile.h>
typedef struct _IpatchRiff IpatchRiff;
typedef struct _IpatchRiffClass IpatchRiffClass;
typedef struct _IpatchRiffChunk IpatchRiffChunk;
#define IPATCH_TYPE_RIFF (ipatch_riff_get_type ())
#define IPATCH_RIFF(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), IPATCH_TYPE_RIFF, IpatchRiff))
#define IPATCH_RIFF_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), IPATCH_TYPE_RIFF, IpatchRiffClass))
#define IPATCH_IS_RIFF(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), IPATCH_TYPE_RIFF))
#define IPATCH_IS_RIFF_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), IPATCH_TYPE_RIFF))
typedef enum
{
IPATCH_RIFF_STATUS_FAIL = 0, /* error occured */
IPATCH_RIFF_STATUS_BEGIN, /* parsing has not yet began */
IPATCH_RIFF_STATUS_FINISHED, /* no more parsing to be done */
IPATCH_RIFF_STATUS_NORMAL, /* normal status */
IPATCH_RIFF_STATUS_CHUNK_END /* end of a chunk */
} IpatchRiffStatus;
typedef enum
{
IPATCH_RIFF_READ,
IPATCH_RIFF_WRITE
} IpatchRiffMode;
/* RIFF object */
struct _IpatchRiff
{
GObject parent_instance; /* derived from GObject */
IpatchRiffStatus status; /* current status */
IpatchRiffMode mode; /* I/O mode (read/write) */
guint flags; /* some flags */
IpatchFileHandle *handle; /* file object being parsed */
GError *err; /* error information if status == IPATCH_RIFF_FAIL */
char *msg_detail; /* last generated message detail string */
GArray *chunks; /* chunk trail (IpatchRiffChunk structures) */
GList *state_stack; /* saved states (positions) */
};
/* RIFF class */
struct _IpatchRiffClass
{
GObjectClass parent_class;
};
#define IPATCH_RIFF_NEED_SWAP(riff) IPATCH_FILE_NEED_SWAP (riff->handle->file)
#define IPATCH_RIFF_BIG_ENDIAN(riff) IPATCH_FILE_BIG_ENDIAN (riff->handle->file)
typedef enum
{
IPATCH_RIFF_CHUNK_RIFF, /* toplevel "RIFF" (or "RIFX") list chunk */
IPATCH_RIFF_CHUNK_LIST, /* a "LIST" chunk */
IPATCH_RIFF_CHUNK_SUB /* a sub chunk */
} IpatchRiffChunkType;
/* structure describing a RIFF chunk */
struct _IpatchRiffChunk
{
IpatchRiffChunkType type; /* type of chunk */
guint32 id; /* chunk ID in integer format for easy comparison */
char idstr[4]; /* four character chunk ID string */
gint32 position; /* current position in chunk (read or write mode) */
guint32 size; /* size of chunk (read mode only) */
guint32 filepos; /* Position in file object of chunk data */
};
/* error domain for g_set_error */
#define IPATCH_RIFF_ERROR ipatch_riff_error_quark()
typedef enum
{
IPATCH_RIFF_ERROR_NOT_RIFF, /* not a RIFF file */
IPATCH_RIFF_ERROR_UNEXPECTED_ID, /* unexpected chunk ID */
IPATCH_RIFF_ERROR_UNEXPECTED_CHUNK_END, /* unexpected LIST chunk end */
IPATCH_RIFF_ERROR_INVALID_ID, /* invalid chunk FOURCC ID */
IPATCH_RIFF_ERROR_ODD_SIZE, /* chunk size is ODD */
IPATCH_RIFF_ERROR_SIZE_EXCEEDED, /* chunk size exceeded */
/* convenience errors - not used by the riff object itself */
IPATCH_RIFF_ERROR_SIZE_MISMATCH, /* chunk size mismatch */
IPATCH_RIFF_ERROR_INVALID_DATA /* generic invalid data error */
} IpatchRiffError;
/* macro to convert 4 char RIFF ids to a guint32 integer for comparisons */
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
#define IPATCH_FOURCC(c1, c2, c3, c4) \
((guint32)(c1) | ((guint32)(c2) << 8) | ((guint32)(c3) << 16) \
| ((guint32)(c4) << 24))
#elif G_BYTE_ORDER == G_BIG_ENDIAN
#define IPATCH_FOURCC(c1, c2, c3, c4) \
((guint32)(c4) | ((guint32)(c3) << 8) | ((guint32)(c2) << 16) \
| ((guint32)(c1) << 24))
#else
#error Processor not big or little endian?
#endif
/* RIFF chunk FOURCC guint32 integers */
#define IPATCH_FOURCC_RIFF IPATCH_FOURCC ('R','I','F','F')
#define IPATCH_FOURCC_RIFX IPATCH_FOURCC ('R','I','F','X') /* big endian */
#define IPATCH_FOURCC_LIST IPATCH_FOURCC ('L','I','S','T')
/**
* IPATCH_RIFF_HEADER_SIZE: (skip)
*/
#define IPATCH_RIFF_HEADER_SIZE 8 /* size of RIFF chunk headers (ID + size) */
/**
* IPATCH_RIFF_FOURCC_SIZE: (skip)
*/
#define IPATCH_RIFF_FOURCC_SIZE 4 /* RIFF FOURCC ID size */
/**
* IPATCH_RIFF_LIST_HEADER_SIZE: (skip)
*/
/* chunk header + 4 character list type */
#define IPATCH_RIFF_LIST_HEADER_SIZE \
(IPATCH_RIFF_HEADER_SIZE + IPATCH_RIFF_FOURCC_SIZE)
/* some RIFF WAVE file specific defines */
/**
* IPATCH_RIFF_WAVE_FMT_PCM: (skip)
*/
#define IPATCH_RIFF_WAVE_FMT_PCM 0x1
/**
* IPATCH_RIFF_WAVE_FMT_FLOAT: (skip)
*/
#define IPATCH_RIFF_WAVE_FMT_FLOAT 0x3
GType ipatch_riff_get_type(void);
GQuark ipatch_riff_error_quark(void);
IpatchRiff *ipatch_riff_new(IpatchFileHandle *handle);
void ipatch_riff_set_file_handle(IpatchRiff *riff, IpatchFileHandle *handle);
IpatchFileHandle *ipatch_riff_get_file_handle(IpatchRiff *riff);
int ipatch_riff_get_chunk_level(IpatchRiff *riff);
IpatchRiffChunk *ipatch_riff_get_chunk_array(IpatchRiff *riff, int *count);
IpatchRiffChunk *ipatch_riff_get_chunk(IpatchRiff *riff, int level);
guint32 ipatch_riff_get_total_size(IpatchRiff *riff);
guint32 ipatch_riff_get_position(IpatchRiff *riff);
void ipatch_riff_push_state(IpatchRiff *riff);
gboolean ipatch_riff_pop_state(IpatchRiff *riff, GError **err);
IpatchRiffChunk *ipatch_riff_start_read(IpatchRiff *riff, GError **err);
IpatchRiffChunk *ipatch_riff_start_read_chunk(IpatchRiff *riff, GError **err);
IpatchRiffChunk *ipatch_riff_read_chunk_verify(IpatchRiff *riff,
IpatchRiffChunkType type,
guint32 id, GError **err);
IpatchRiffChunk *ipatch_riff_read_chunk(IpatchRiff *riff, GError **err);
#define ipatch_riff_write_list_chunk(parser, id, err) \
ipatch_riff_write_chunk (parser, IPATCH_RIFF_CHUNK_LIST, id, err)
#define ipatch_riff_write_sub_chunk(parser, id, err) \
ipatch_riff_write_chunk (parser, IPATCH_RIFF_CHUNK_SUB, id, err)
gboolean ipatch_riff_write_chunk(IpatchRiff *riff, IpatchRiffChunkType type,
guint32 id, GError **err);
#define ipatch_riff_end_chunk(parser, err) \
ipatch_riff_close_chunk (parser, -1, err)
gboolean ipatch_riff_close_chunk(IpatchRiff *riff, int level, GError **err);
#define ipatch_riff_skip_chunk(parser, err) \
ipatch_riff_skip_chunks (parser, 1, err)
gboolean ipatch_riff_skip_chunks(IpatchRiff *riff, guint count, GError **err);
gboolean ipatch_riff_get_error(IpatchRiff *riff, GError **err);
char *ipatch_riff_message_detail(IpatchRiff *riff, int level,
const char *format, ...);
#endif