1 /* mode_cue.c - cue sheet mode module
2 * Copyright (C) 2000-2009 Jason Jordan <shnutils@freeshell.org>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 #include <string.h>
20 #include "mode.h"
21
22 CVSID("$Id: mode_cue.c,v 1.48 2009/03/17 17:23:05 jason Exp $")
23
24 static bool cue_main(int,char **);
25 static void cue_help(void);
26
27 mode_module mode_cue = {
28 "cue",
29 "shncue",
30 "Generates a CUE sheet or split points from a set of files",
31 CVSIDSTR,
32 FALSE,
33 cue_main,
34 cue_help
35 };
36
37 enum {
38 TYPE_UNKNOWN,
39 TYPE_CUESHEET,
40 TYPE_SPLITPOINTS
41 };
42
43 static int output_type = TYPE_UNKNOWN;
44
45 static double total_data_size = 0.0;
46 static int numfiles = 0;
47
48 static wave_info *totals = NULL;
49
cue_help()50 static void cue_help()
51 {
52 st_info("Usage: %s [OPTIONS] [files]\n",st_progname());
53 st_info("\n");
54 st_info("Mode-specific options:\n");
55 st_info("\n");
56 st_info(" -c generate CUE sheet (default)\n");
57 st_info(" -h show this help screen\n");
58 st_info(" -s generate split points in explicit byte-offset format\n");
59 st_info("\n");
60 }
61
parse(int argc,char ** argv,int * first_arg)62 static void parse(int argc,char **argv,int *first_arg)
63 {
64 int c;
65
66 output_type = TYPE_CUESHEET;
67
68 while ((c = st_getopt(argc,argv,"cs")) != -1) {
69 switch (c) {
70 case 'c':
71 output_type = TYPE_CUESHEET;
72 break;
73 case 's':
74 output_type = TYPE_SPLITPOINTS;
75 break;
76 }
77 }
78
79 *first_arg = optind;
80 }
81
verify_wave_info(wave_info * info)82 static void verify_wave_info(wave_info *info)
83 {
84 if ((TYPE_CUESHEET == output_type) && PROB_NOT_CD(info)) {
85 st_error("file is not CD-quality: [%s]",info->filename);
86 }
87
88 if (0 == totals->wave_format && 0 == totals->channels &&
89 0 == totals->samples_per_sec && 0 == totals->avg_bytes_per_sec &&
90 0 == totals->bits_per_sample && 0 == totals->block_align) {
91 totals->wave_format = info->wave_format;
92 totals->channels = info->channels;
93 totals->samples_per_sec = info->samples_per_sec;
94 totals->avg_bytes_per_sec = info->avg_bytes_per_sec;
95 totals->bits_per_sample = info->bits_per_sample;
96 totals->block_align = info->block_align;
97 totals->problems = info->problems;
98 return;
99 }
100
101 if (info->wave_format != totals->wave_format)
102 st_error("WAVE format differs among these files");
103
104 if (info->channels != totals->channels)
105 st_error("number of channels differs among these files");
106
107 if (info->samples_per_sec != totals->samples_per_sec)
108 st_error("samples per second differs among these files");
109
110 if (info->avg_bytes_per_sec != totals->avg_bytes_per_sec)
111 st_error("average bytes per second differs among these files");
112
113 if (info->bits_per_sample != totals->bits_per_sample)
114 st_error("bits per sample differs among these files");
115
116 if (info->block_align != totals->block_align) {
117 st_warning("block align differs among these files");
118 }
119 }
120
output_init()121 static void output_init()
122 {
123 if (NULL == (totals = new_wave_info(NULL)))
124 st_error("could not allocate memory for totals");
125
126 if (output_type == TYPE_CUESHEET) {
127 st_output("FILE \"joined.wav\" WAVE\n");
128 }
129 }
130
output_track(char * filename)131 static bool output_track(char *filename)
132 {
133 wave_info *info;
134 wlong curr_data_size = 0;
135 char *p;
136
137 if (NULL == (info = new_wave_info(filename)))
138 return FALSE;
139
140 verify_wave_info(info);
141
142 numfiles++;
143
144 curr_data_size = info->data_size;
145
146 if (output_type == TYPE_CUESHEET) {
147 info->data_size = (wlong)total_data_size;
148 info->length = info->data_size / info->rate;
149 length_to_str(info);
150 if ((p = strstr(info->m_ss,".")))
151 *p = ':';
152 st_output(" TRACK %02d AUDIO\n",numfiles);
153 st_output(" INDEX 01 %s\n",info->m_ss);
154 }
155 else if (output_type == TYPE_SPLITPOINTS) {
156 if (total_data_size > 0.0)
157 st_output("%0.0f\n",total_data_size);
158 }
159
160 total_data_size += (double)curr_data_size;
161
162 return TRUE;
163 }
164
output_end()165 static void output_end()
166 {
167 if (TYPE_CUESHEET == output_type && numfiles < 1) {
168 st_error("need one or more files in order to generate CUE sheet");
169 }
170
171 if (TYPE_SPLITPOINTS == output_type && numfiles < 2) {
172 st_error("need two or more files in order to generate split points");
173 }
174 }
175
process(int argc,char ** argv,int start)176 static bool process(int argc,char **argv,int start)
177 {
178 char *filename;
179 bool success;
180
181 success = TRUE;
182
183 output_init();
184
185 input_init(start,argc,argv);
186
187 while ((filename = input_get_filename())) {
188 success = (output_track(filename) && success);
189 }
190
191 output_end();
192
193 return success;
194 }
195
cue_main(int argc,char ** argv)196 static bool cue_main(int argc,char **argv)
197 {
198 int first_arg;
199
200 parse(argc,argv,&first_arg);
201
202 return process(argc,argv,first_arg);
203 }
204