summaryrefslogtreecommitdiff
path: root/plugins/shn/shn.h
blob: 518334bc770c5feb6baf18ae66fb4b44bd71c990 (plain)
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
/*  xmms-shn - a shorten (.shn) plugin for XMMS
 *  Copyright (C) 2000-2007  Jason Jordan <shnutils@freeshell.org>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

/*
 * $Id: shn.h,v 1.27 2007/03/23 05:49:48 jason Exp $
 */

#ifndef _SHN_H
#define _SHN_H

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include "../../deadbeef.h"

extern DB_functions_t *deadbeef;

#define shn_vsnprintf(a,b,c,d) vsnprintf(a,b,c,d)

#define	min(a,b)			(((a)<(b))?(a):(b))

/* surely no headers will be this large.  right?  RIGHT?  */
#define OUT_BUFFER_SIZE			16384

#define BUF_SIZE                        4096

#define	ERROR_OUTPUT_DEVNULL		0
#define	ERROR_OUTPUT_STDERR		1
#define	ERROR_OUTPUT_WINDOW		2

#define	SEEK_SUFFIX			"skt"

#define	NO_SEEK_TABLE			-1

#define	SEEK_HEADER_SIGNATURE		"SEEK"
#define	SEEK_TRAILER_SIGNATURE		"SHNAMPSK"

#define SEEK_HEADER_SIZE		12
#define SEEK_TRAILER_SIZE		12
#define SEEK_ENTRY_SIZE			80
#define SEEK_RESOLUTION			25600

#define WAVE_RIFF                       (0x46464952)     /* 'RIFF' in little-endian */
#define WAVE_WAVE                       (0x45564157)     /* 'WAVE' in little-endian */
#define WAVE_FMT                        (0x20746d66)     /* ' fmt' in little-endian */
#define WAVE_DATA                       (0x61746164)     /* 'data' in little-endian */

#define AIFF_FORM                       (0x4D524F46)     /* 'FORM' in little-endian */

#define WAVE_FORMAT_UNKNOWN             (0x0000)
#define WAVE_FORMAT_PCM                 (0x0001)
#define WAVE_FORMAT_ADPCM               (0x0002)
#define WAVE_FORMAT_IEEE_FLOAT          (0x0003)
#define WAVE_FORMAT_ALAW                (0x0006)
#define WAVE_FORMAT_MULAW               (0x0007)
#define WAVE_FORMAT_OKI_ADPCM           (0x0010)
#define WAVE_FORMAT_IMA_ADPCM           (0x0011)
#define WAVE_FORMAT_DIGISTD             (0x0015)
#define WAVE_FORMAT_DIGIFIX             (0x0016)
#define WAVE_FORMAT_DOLBY_AC2           (0x0030)
#define WAVE_FORMAT_GSM610              (0x0031)
#define WAVE_FORMAT_ROCKWELL_ADPCM      (0x003b)
#define WAVE_FORMAT_ROCKWELL_DIGITALK   (0x003c)
#define WAVE_FORMAT_G721_ADPCM          (0x0040)
#define WAVE_FORMAT_G728_CELP           (0x0041)
#define WAVE_FORMAT_MPEG                (0x0050)
#define WAVE_FORMAT_MPEGLAYER3          (0x0055)
#define WAVE_FORMAT_G726_ADPCM          (0x0064)
#define WAVE_FORMAT_G722_ADPCM          (0x0065)

#define CD_BLOCK_SIZE                   (2352)
#define CD_BLOCKS_PER_SEC               (75)
#define CD_MIN_BURNABLE_SIZE            (705600)
#define CD_CHANNELS                     (2)
#define CD_SAMPLES_PER_SEC              (44100)
#define CD_BITS_PER_SAMPLE              (16)
#define CD_RATE                         (176400)

#define CANONICAL_HEADER_SIZE           (44)

#define PROBLEM_NOT_CD_QUALITY          (0x00000001)
#define PROBLEM_CD_BUT_BAD_BOUND        (0x00000002)
#define PROBLEM_CD_BUT_TOO_SHORT        (0x00000004)
#define PROBLEM_HEADER_NOT_CANONICAL    (0x00000008)
#define PROBLEM_EXTRA_CHUNKS            (0x00000010)
#define PROBLEM_HEADER_INCONSISTENT     (0x00000020)

#define PROB_NOT_CD(f)                  ((f.problems) & (PROBLEM_NOT_CD_QUALITY))
#define PROB_BAD_BOUND(f)               ((f.problems) & (PROBLEM_CD_BUT_BAD_BOUND))
#define PROB_TOO_SHORT(f)               ((f.problems) & (PROBLEM_CD_BUT_TOO_SHORT))
#define PROB_HDR_NOT_CANONICAL(f)       ((f.problems) & (PROBLEM_HEADER_NOT_CANONICAL))
#define PROB_EXTRA_CHUNKS(f)            ((f.problems) & (PROBLEM_EXTRA_CHUNKS))
#define PROB_HDR_INCONSISTENT(f)        ((f.problems) & (PROBLEM_HEADER_INCONSISTENT))

#include <limits.h>

#ifndef PATH_MAX
#define PATH_MAX    1024    /* max # of characters in a path name */
#endif

typedef struct _shn_config
{
	int      error_output_method;
	char    seek_tables_path[PATH_MAX];
	char    relative_seek_tables_path[PATH_MAX];
	int  verbose;
	int  swap_bytes;
} shn_config;

typedef struct _shn_decode_state
{
	uchar *getbuf;
	uchar *getbufp;
	int    nbitget;
	int    nbyteget;
	ulong  gbuffer;
	schar *writebuf;
	schar *writefub;
	int    nwritebuf;
} shn_decode_state;

typedef struct _shn_seek_header
{
	uchar data[SEEK_HEADER_SIZE];
	slong version;
	ulong shnFileSize;	
} shn_seek_header;

typedef struct _shn_seek_trailer
{
	uchar data[SEEK_TRAILER_SIZE];
	ulong seekTableSize;
} shn_seek_trailer;

typedef struct _shn_seek_entry
{
	uchar data[SEEK_ENTRY_SIZE];
} shn_seek_entry;

/* old way, kept for reference.
   (changed because some compilers apparently don't support #pragma pack(1))

typedef struct _shn_seek_header
{
	char signature[4];
	unsigned long version;
	unsigned long shnFileSize;
} shn_seek_header;

typedef struct _shn_seek_trailer
{
	unsigned long seekTableSize;
	char signature[8];
} shn_seek_trailer;

typedef struct _shn_seek_entry
{
	unsigned long  shnSample;
	unsigned long  shnByteOffset;
	unsigned long  shnLastPosition;
	unsigned short shnByteGet;
	unsigned short shnBufferOffset;
	unsigned short shnBitOffset;
	unsigned long  shnGBuffer;
	unsigned short shnBitShift;
	long cbuf0[3];
	long cbuf1[3];
	long offset0[4];
	long offset1[4];
} shn_seek_entry;
*/

typedef struct _shn_wave_header
{
	const char *filename;
    char m_ss[16];

	uint header_size;

	ushort channels,
	       block_align,
	       bits_per_sample,
	       wave_format;

	ulong samples_per_sec,
	      avg_bytes_per_sec,
	      rate,
	      length,
	      data_size,
	      total_size,
	      chunk_size,
	      actual_size;

	double exact_length;

	int   file_has_id3v2_tag;
	long  id3v2_tag_size;

	ulong problems;
} shn_wave_header;

typedef struct _shn_vars
{
	DB_FILE  *fd;
	int    seek_to;
	int    eof;
	int    going;
	slong  seek_table_entries;
	ulong  seek_resolution;
	int    bytes_in_buf;
	uchar  buffer[OUT_BUFFER_SIZE];
	int    bytes_in_header;
	uchar  header[OUT_BUFFER_SIZE];
	int    fatal_error;
	schar  fatal_error_msg[BUF_SIZE];
	int    reading_function_code;
	ulong  last_file_position;
	ulong  last_file_position_no_really;
	ulong  initial_file_position;
	ulong  bytes_read;
	unsigned short actual_bitshift;
	int    actual_maxnlpc;
	int    actual_nmean;
	int    actual_nchan;
	long   seek_offset;
} shn_vars;

typedef struct _shn_file
{
	shn_vars          vars;
	shn_decode_state *decode_state;
	shn_wave_header   wave_header;
	shn_seek_header   seek_header;
	shn_seek_trailer  seek_trailer;
	shn_seek_entry   *seek_table;
} shn_file;

extern shn_config shn_cfg;

extern shn_seek_entry *shn_seek_entry_search(shn_seek_entry *,ulong,ulong,ulong,ulong);
extern void shn_load_seek_table(shn_file *,const char *);
extern void shn_unload(shn_file *);
extern int shn_verify_header(shn_file *);
extern int shn_filename_contains_a_dot(const char *);
extern char *shn_get_base_filename(const char *);
extern char *shn_get_base_directory(const char *);
extern void shn_length_to_str(shn_file *);
extern char *shn_format_to_str(ushort);
extern ulong shn_uchar_to_ulong_le(uchar *);
extern slong shn_uchar_to_slong_le(uchar *);
extern ushort shn_uchar_to_ushort_le(uchar *);
extern void shn_debug(char *, ...);
extern void shn_error(char *, ...);
extern void shn_error_fatal(shn_file *,char *, ...);
extern void shn_snprintf(char *,int,char *, ...);

#endif