1 /* mode_gen.c - gen 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_gen.c,v 1.53 2009/03/16 04:46:03 jason Exp $")
23
24 static bool gen_main(int,char **);
25 static void gen_help(void);
26
27 mode_module mode_gen = {
28 "gen",
29 "shngen",
30 "Generates CD-quality PCM WAVE data files containing silence",
31 CVSIDSTR,
32 TRUE,
33 gen_main,
34 gen_help
35 };
36
37 #define GEN_PREFIX "silence"
38
39 static char *gen_size = NULL;
40
gen_help()41 static void gen_help()
42 {
43 st_info("Usage: %s [OPTIONS]\n",st_progname());
44 st_info("\n");
45 st_info("Mode-specific options:\n");
46 st_info("\n");
47 st_info(" -h show this help screen\n");
48 st_info(" -l len generate files containing silence of length len (*)\n");
49 st_info("\n");
50 st_info(" (*) len must be in bytes, m:ss, m:ss.ff or m:ss.nnn format\n");
51 st_info("\n");
52 }
53
parse(int argc,char ** argv)54 static void parse(int argc,char **argv)
55 {
56 int c;
57
58 st_ops.output_directory = CURRENT_DIR;
59 st_ops.output_prefix = GEN_PREFIX;
60
61 while ((c = st_getopt(argc,argv,"l:")) != -1) {
62 switch (c) {
63 case 'l':
64 if (NULL == optarg)
65 st_error("missing silence length");
66 gen_size = optarg;
67 break;
68 }
69 }
70
71 if (NULL == gen_size)
72 st_error("length must be specified");
73 }
74
process()75 static bool process()
76 {
77 wave_info *info;
78 unsigned char header[CANONICAL_HEADER_SIZE],silence[XFER_SIZE];
79 char outfilename[FILENAME_SIZE];
80 FILE *output;
81 proc_info output_proc;
82 wlong gen_bytes,bytes_left,bytes;
83 progress_info proginfo;
84 bool success;
85
86 success = FALSE;
87
88 if (NULL == (info = new_wave_info(NULL))) {
89 st_error("could not allocate memory for WAVE info");
90 }
91
92 info->rate = CD_RATE;
93
94 gen_bytes = smrt_parse((unsigned char *)gen_size,info);
95
96 create_output_filename("","",outfilename);
97
98 info->channels = CD_CHANNELS;
99 info->samples_per_sec = CD_SAMPLES_PER_SEC;
100 info->avg_bytes_per_sec = CD_RATE;
101 info->block_align = CD_BLOCK_ALIGN;
102 info->bits_per_sample = CD_BITS_PER_SAMPLE;
103 info->wave_format = WAVE_FORMAT_PCM;
104 info->rate = CD_RATE;
105
106 info->data_size = gen_bytes;
107 info->chunk_size = info->data_size + CANONICAL_HEADER_SIZE - 8;
108 info->length = info->data_size / (wlong)info->rate;
109 info->exact_length = (double)info->data_size / (double)info->rate;
110
111 if (PROB_ODD_SIZED_DATA(info))
112 info->chunk_size++;
113
114 make_canonical_header(header,info);
115
116 length_to_str(info);
117
118 bytes_left = gen_bytes;
119
120 memset((void *)silence,0,XFER_SIZE);
121
122 proginfo.initialized = FALSE;
123 proginfo.prefix = "Generating";
124 proginfo.clause = NULL;
125 proginfo.filename1 = NULL;
126 proginfo.filedesc1 = NULL;
127 proginfo.filename2 = outfilename;
128 proginfo.filedesc2 = info->m_ss;
129 proginfo.bytes_total = bytes_left + CANONICAL_HEADER_SIZE;
130
131 prog_update(&proginfo);
132
133 if (NULL == (output = open_output_stream(outfilename,&output_proc)))
134 st_error("could not open output file: [%s]",outfilename);
135
136 if (write_n_bytes(output,header,CANONICAL_HEADER_SIZE,&proginfo) != CANONICAL_HEADER_SIZE) {
137 prog_error(&proginfo);
138 st_error("error while writing %d-byte WAVE header",CANONICAL_HEADER_SIZE);
139 }
140
141 while (bytes_left > 0) {
142 bytes = min(bytes_left,XFER_SIZE);
143
144 if (write_n_bytes(output,silence,bytes,&proginfo) != bytes) {
145 prog_error(&proginfo);
146 st_error("error while writing %d-byte chunk of silence",bytes);
147 }
148
149 bytes_left -= bytes;
150 }
151
152 if (PROB_ODD_SIZED_DATA(info) && (1 != write_padding(output,1,&proginfo))) {
153 prog_error(&proginfo);
154 st_error("error while NULL-padding odd-sized data chunk");
155 }
156
157 success = TRUE;
158
159 prog_success(&proginfo);
160
161 if (CLOSE_CHILD_ERROR_OUTPUT == close_output(output,output_proc)) {
162 success = FALSE;
163 }
164
165 return success;
166 }
167
gen_main(int argc,char ** argv)168 static bool gen_main(int argc,char **argv)
169 {
170 parse(argc,argv);
171
172 return process();
173 }
174