Add Russian translation provided by Валерий Крувялис <valkru@mail.ru>
[xiph-mirror.git] / spectrum / waveform.c
blob7db856b2d262d6fa21236123327e3d47effc092f
1 /*
3 * gtk2 waveform viewer
5 * Copyright (C) 2004-2012 Monty
7 * This analyzer is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
12 * The analyzer is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Postfish; see the file COPYING. If not, write to the
19 * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "waveform.h"
25 #include <signal.h>
26 #include <getopt.h>
27 #include <fenv.h> // Thank you C99!
28 #include <gtk/gtk.h>
29 #include "version.h"
30 #include "io.h"
32 int eventpipe[2];
33 char *version;
34 char *inputname[MAX_FILES];
35 int inputs=0;
36 int blocksize=0;
37 extern int plot_bold;
39 void handler(int sig){
40 signal(sig,SIG_IGN);
41 if(sig!=SIGINT){
42 fprintf(stderr,
43 "\nTrapped signal %d; exiting!\n"
44 "This signal almost certainly indicates a bug in the analyzer;\n"
45 "If this version of the analyzer is newer than a few months old,\n"
46 "please email a detailed report of the crash along with\n"
47 "processor type, OS version, and as much information as possible\n"
48 "about what caused the crash. The best possible report will\n"
49 "outline the exact steps needed to reproduce the error, ensuring\n"
50 "that I can fix the bug as quickly as possible.\n\n"
51 "-- monty@xiph.org, spectrum revision %s\n\n",sig,version);
54 gtk_main_quit();
57 const char *optstring = "-r:c:EeBlb:suhT";
59 struct option options [] = {
60 {"bold",no_argument,NULL,'T'},
61 {"rate",required_argument,NULL,'r'},
62 {"channels",required_argument,NULL,'c'},
63 {"big-endian",no_argument,NULL,'E'},
64 {"little-endian",no_argument,NULL,'e'},
65 {"bits",required_argument,NULL,'b'},
66 {"signed",no_argument,NULL,'s'},
67 {"unsigned",no_argument,NULL,'u'},
68 {"help",no_argument,NULL,'h'},
70 {NULL,0,NULL,0}
73 static void usage(FILE *f){
74 fprintf( f,
75 "\ngtk2 waveform viewer, revision %s\n\n"
77 "USAGE:\n\n"
78 " waveform [options] [file]\n\n"
80 "OPTIONS:\n\n"
81 " -b --bits <bits> : Force input to be read as 8, 16, 24 or 32 bit\n"
82 " PCM. Default bit depth is normally read from\n"
83 " the file/stream header or set to 16 bits\n"
84 " for raw input.\n"
85 " -B -E --big-endian : Force input to be read as big endian.\n"
86 " Default endianness is normally read from the\n"
87 " file/stream header or set to host"
88 " endianness for raw input.\n"
89 " -c --channels <channels> : Input channel number override; use to\n"
90 " specify the number of channels in a raw\n"
91 " input. default: 1\n"
92 " -e -l --little-endian : Force input to be read as little endian.\n"
93 " Default endianness is normally read from the\n"
94 " file/stream header or set to host"
95 " endianness for raw input.\n"
96 " -h --help : print this help\n"
97 " -r --rate <Hz> : Input sample rate override in Hz; use to\n"
98 " specify the rate of a raw input.\n"
99 " default: 44100\n"
100 " -s --signed : Force input to be read as signed PCM.\n"
101 " Signedness is normally read from the \n"
102 " file/stream header or set to signed for raw\n"
103 " input.\n"
104 " -T --bold : plot spectrum with thicker/bolder lines.\n"
105 " -u --unsigned : Force input to be read as unsigned PCM.\n"
106 " Signedness is normally read from the \n"
107 " file/stream header or set to signed for raw\n"
108 " input.\n\n"
110 "INPUT:\n\n"
112 " Waveform takes raw, WAV or AIFF input either from stdin or from \n"
113 " file[s]/stream[s] specified on the command line.\n\n",version);
117 void parse_command_line(int argc, char **argv){
118 int c,long_option_index;
120 while((c=getopt_long(argc,argv,optstring,options,&long_option_index))!=EOF){
121 switch(c){
122 case 1:
123 /* file name that belongs to current group */
124 if(inputs>=MAX_FILES){
125 fprintf(stderr,"Maximum of MAX_FILES input files exceeded. Oops. Programmer was lazy.\n\n");
126 exit(1);
128 inputname[inputs++]=strdup(optarg);
129 break;
130 case 'T':
131 plot_bold = 1;
132 break;
133 case 'b':
134 /* force bit width */
136 int a=atoi(optarg);
137 bits[inputs]=a;
138 bits_force[inputs]=1;
139 if(a!=8 && a!=16 && a!=24 && a!=32){
140 usage(stderr);
141 exit(1);
144 break;
145 case 'B':case 'E':
146 /* force big endian */
147 bigendian[inputs]=1;
148 bigendian_force[inputs]=1;
149 break;
150 case 'c':
151 /* force channels */
153 int a=atoi(optarg);
154 channels[inputs]=a;
155 channels_force[inputs]=1;
156 if(a<1 || a>32){
157 usage(stderr);
158 exit(1);
161 break;
162 case 'l':case 'e':
163 /* force little endian */
164 bigendian[inputs]=0;
165 bigendian_force[inputs]=1;
166 break;
167 case 'h':
168 usage(stdout);
169 exit(0);
170 case 'r':
171 /* force rate */
173 int a=atoi(optarg);
174 rate[inputs]=a;
175 rate_force[inputs]=1;
176 if(a<4000 || a>200000){
177 usage(stderr);
178 exit(1);
181 break;
182 case 's':
183 /* force signed */
184 signedp[inputs]=1;
185 signed_force[inputs]=1;
186 break;
187 case 'u':
188 /* force unsigned */
189 signedp[inputs]=0;
190 signed_force[inputs]=1;
191 break;
192 default:
193 usage(stderr);
194 exit(0);
199 static int sigill=0;
200 void sigill_handler(int sig){
201 /* make sure */
202 if(sig==SIGILL)sigill=1;
205 int main(int argc, char **argv){
206 int fi;
208 version=strstr(VERSION,"version.h");
209 if(version){
210 char *versionend=strchr(version,' ');
211 if(versionend)versionend=strchr(versionend+1,' ');
212 if(versionend)versionend=strchr(versionend+1,' ');
213 if(versionend)versionend=strchr(versionend+1,' ');
214 if(versionend){
215 int len=versionend-version-9;
216 version=strdup(version+10);
217 version[len-1]=0;
219 }else{
220 version="";
223 /* parse command line and open all the input files */
224 parse_command_line(argc, argv);
226 /* We do not care about FPEs; rather, underflow is nominal case, and
227 its better to ignore other traps in production than to crash the
228 app. Please inform the FPU of this. */
230 #ifndef DEBUG
231 fedisableexcept(FE_INVALID);
232 fedisableexcept(FE_INEXACT);
233 fedisableexcept(FE_UNDERFLOW);
234 fedisableexcept(FE_OVERFLOW);
235 #else
236 feenableexcept(FE_INVALID);
237 feenableexcept(FE_INEXACT);
238 feenableexcept(FE_UNDERFLOW);
239 feenableexcept(FE_OVERFLOW);
240 #endif
242 /* Linux Altivec support has a very annoying problem; by default,
243 math on denormalized floats will simply crash the program. FFTW3
244 uses Altivec, so boom, but only random booms.
246 By the C99 spec, the above exception configuration is also
247 supposed to handle Altivec config, but doesn't. So we use the
248 below ugliness to both handle altivec and non-alitvec PPC. */
250 #ifdef __PPC
251 #include <altivec.h>
252 signal(SIGILL,sigill_handler);
254 #if (defined __GNUC__) && (__GNUC__ == 3) && ! (defined __APPLE_CC__)
255 __vector unsigned short noTrap =
256 (__vector unsigned short){0,0,0,0,0,0,0x1,0};
257 #else
258 vector unsigned short noTrap =
259 (vector unsigned short)(0,0,0,0,0,0,0x1,0);
260 #endif
262 vec_mtvscr(noTrap);
263 #endif
265 /* easiest way to inform gtk of changes and not deal with locking
266 issues around the UI */
267 if(pipe(eventpipe)){
268 fprintf(stderr,"Unable to open event pipe:\n"
269 " %s\n",strerror(errno));
271 exit(1);
274 /* Allows event compression on the read side */
275 if(fcntl(eventpipe[0], F_SETFL, O_NONBLOCK)){
276 fprintf(stderr,"Unable to set O_NONBLOCK on event pipe:\n"
277 " %s\n",strerror(errno));
279 exit(1);
282 //signal(SIGINT,handler);
283 signal(SIGSEGV,handler);
285 if(input_load())exit(1);
287 /* set block size equal to maximum input rate + epsilon*/
288 /* (maximum display width: 1s, maximum update interval 1s) */
289 blocksize=0;
290 for(fi=0;fi<inputs;fi++)
291 if(rate[fi]>blocksize)blocksize=rate[fi]+16;
293 /* begin with a display width of 1s */
294 /* begin with an update interval (blockslice) of 100ms */
295 blockslice_frac = 10;
297 panel_go(argc,argv);
299 return(0);