File: mp3_check.c

package info (click to toggle)
checkmp3 1.98-6
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 180 kB
  • ctags: 136
  • sloc: ansic: 1,212; makefile: 60
file content (225 lines) | stat: -rw-r--r-- 5,255 bytes parent folder | download | duplicates (5)
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
/**********************************************************************
PROGRAM NAME:	mp3_check

VERSION:	1.97	

AUTHOR:		Eric Bullen <ericb@thedeepsky.com>

PURPOSE:	Identify in explicit detail mp3s that do not correctly
		follow the mp3 format. Also look for invalid frame
		headers, missing frames, etc. This can be especially
		important when building an archive, and you want 
		quality mp3s.

USAGE:		mp3s are accepted either from stdin, or on the
		command-line. Statistical data and summary information
		is sent to stout, and any errors are sent to stderr. 
		More information is available by using the '-h' switch
		on the commandline.

		Common execution can be:
		========================

		cat some_song.mp3 | mp3_check -s - | mpg123

		OR

		mp3_check -a -v some_song.mp3

		INTERESTING TEST

		mp3_check -b100000 -vv /dev/urandom
		

REFERENCES:	All original code. However the format of an mp3 file
		was obtained from long-lost web sites and nntp articles.

RESTRICTIONS:	This program has been released under the GNU GPL license.
		
REVISIONS: 	27-Mar-00: Initial release v.1.0.

NOTES:		One area that could use some improvement is in the
		function:

		check_header_value

		The check_header_value could use some more error checking.

DOWNLOADING:	The master ftp archive for new versions is: 
		ftp://ftp.thedeepsky.com/outgoing/ 

GOALS:		Initially, making a higly accurate mp3 analysis tool is the
		goal, however, building a solid framework for a command-line
		mp3 player is a possibility. I wanted clean, readable code
		so it is easily expandable to do a variety of things. With
		readable code, more people can follow my logic, and find
		improvements quicker and easier.


**********************************************************************/

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include "mp3_check.h"

// FUNCTION PROTOTYPES HAPPEN HERE 
extern	int		parse_args(char **argv, meta_options *flag_options, command_flags *flags);
extern	void		print_usage(void);
extern	void            init_command_flags_struct(command_flags *flags);
extern	void		print_sys_usage(void);

int
main(argc, argv)
	int argc;
	char *argv[];
{
	int ch;

	int got_error = 0;
	command_flags flags;
	meta_options flag_options;

	init_command_flags_struct(&flags);

	while ((ch = getopt(argc, argv, "q:epv::ahs::ib::")) != -1)
		switch (ch) {
			case 'q':
				// Determine a mininum number of
				// contiguous frames that must be
				// present for an error not to occur.
				// Reason why is that mp3 headers are very
				// easy to generate, and often this is
				// the best way to see if it is actually
				// an mp3 and not some random data.

				// The 'q' is for se'q'uence.
	
				// NOTE TO SELF: Why isn't the single ':' forcing 
				// an option to be there? Weird.	

				if (atoi(optarg) > 1) {
					flag_options.min_frame_seq = atoi(optarg);	
					flags.qflag = TRUE;
				
				} else {
					(void)fprintf(stderr, "You must supply an integer greater than 1 to use the '-q' flag.");
					
					return(FAIL - 1);						
				}

				break;
			case 'e':
				// Record an invalid frame
				// when an id3v2 tag is found.
				flags.eflag = TRUE;
	
				break;
			case 'p':
				// Single-line output only 
				// for easier parsing.
				flags.pflag = TRUE;
				
				break;
			case 'v':
				//  Verbose 
				flags.vflag = TRUE;

				//  Be very verbose - every pice of cool 
				//  info about each frame is shot to the screen 
				if (optarg && *optarg == 'v')
					flags.vvflag = TRUE;
	
				break;

			case 'a':
				//  Check the whole mp3 
				flags.aflag = TRUE;
				break;
				
			case 's':
				//  Send mp3 to stdout 
				flags.sflag = TRUE;

				//  Be betty quiet. I do not want any 
				//  output unless it is an error. 

				if (optarg && *optarg == 's')
					flags.ssflag = TRUE;

				if (optarg && *optarg == 'f') {
					flags.fflag = TRUE;
					//flags.sflag = FALSE;
				}

				break;
				
			case 'i':
				//  Check for that pesky id3 tag. It is going 
				//  to run a LOT slower with this on. 
				flags.iflag = TRUE;
				break;
				
			case 'b':
				//  Only scan the first # of bytes, then quit. 
				if (optarg)
					flag_options.byte_limit = atoi(optarg);
	
				flags.bflag = TRUE;
				break;
				
			case 'h':
				//  What? You need the help message? 
				print_usage();
				break;
				
			default:
				print_usage();
				break;
		}

	argv += optind;

	//
	// If there's no data after the flags, return an error.
	//
	if (*argv == NULL) {
		print_usage();
	}


	//  
	//  Required fields go here. Everything 
	//  else not listed here are optional. 
	//  
	//  The below 'if' statement seems a little silly, 
	//  but it works. I will clean it up a little later. 
	//  
	if (!(flags.vflag || flags.aflag || flags.bflag))
		flags.aflag = TRUE;

	if (!flags.aflag)
		flags.bflag = TRUE;


	// parse_args is where the program begins.
	// everything else stems from it.
	if (!parse_args(argv, &flag_options, &flags))
		got_error++;

	if (!flags.sflag)
		print_sys_usage();


	//
	// At least in bash, I have to return a '0' to indicate
	// a success, while in C, a success is typically a '1'.
	//
	if (got_error > 0)
		return(FAIL - 1);
	else
		return(PASS - 1);

} // MAIN