Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 #include "config.h"
  2 
  3 #include <stdio.h>
  4 #include <stdlib.h>
  5 #include <string.h>
  6 #include <unistd.h>
  7 #include <fcntl.h>
  8 #include <errno.h>
  9 #include <curses.h>
 10 #include <signal.h>
 11 #include <inttypes.h>
 12 #include <sys/time.h>
 13 #include <sys/signal.h>
 14 #include <sys/ioctl.h>
 15 #include <sys/types.h>
 16 #ifdef HAVE_SOUNDCARD_H
 17 # include <soundcard.h>
 18 #endif
 19 #ifdef HAVE_SYS_SOUNDCARD_H
 20 # include <sys/soundcard.h>
 21 #endif
 22 
 23 /* -------------------------------------------------------------------- */
 24 
 25 static void
 26 tty_raw(void)
 27 {
 28     initscr();
 29     cbreak();
 30     noecho();
 31     keypad(stdscr,1);
 32     refresh();
 33 }
 34 
 35 static void
 36 tty_restore(void)
 37 {
 38     endwin();
 39 }
 40 
 41 /* -------------------------------------------------------------------- */
 42 
 43 static int           sound_fd;
 44 static int           sound_rcount;
 45 static unsigned int  sound_blksize;
 46 static int16_t       *sound_buffer;
 47 static int           maxl,maxr;
 48 static int           secl,secr;
 49 static int           *histl,*histr,histn,histi;
 50 static float         peak_seconds = 1.5;
 51 static char          *audio_dev = "/dev/dsp";
 52 
 53 static int
 54 sound_open(int rate)
 55 {
 56     int frag,afmt,channels,trigger,srate;
 57     
 58     if (-1 == (sound_fd = open(audio_dev, O_RDONLY))) {
 59         fprintf(stderr,"open %s: %s\n",audio_dev,strerror(errno));
 60         exit(1);
 61     }
 62 
 63     frag = 0x7fff000d; /* 8k */
 64     if (-1 == ioctl(sound_fd, SNDCTL_DSP_SETFRAGMENT, &frag))
 65         perror("ioctl SNDCTL_DSP_SETFRAGMENT");
 66 
 67     /* format */
 68     afmt = AFMT_S16_LE;
 69     if (-1 == ioctl(sound_fd, SNDCTL_DSP_SETFMT, &afmt)) {
 70         perror("ioctl SNDCTL_DSP_SETFMT");
 71         exit(1);
 72     }
 73     if (afmt != AFMT_S16_LE) {
 74         fprintf(stderr,"can't set sound format to 16 bit (le)\n");
 75         exit(1);
 76     }
 77 
 78     /* channels */
 79     channels = 2;
 80     if (-1 == ioctl(sound_fd, SNDCTL_DSP_CHANNELS, &channels)) {
 81         perror("ioctl SNDCTL_DSP_CHANNELS");
 82         exit(1);
 83     }
 84     if (channels != 2) {
 85         fprintf(stderr,"can't record in stereo\n");
 86         exit(1);
 87     }
 88 
 89     /* rate */
 90     srate = rate;
 91     if (-1 == ioctl(sound_fd, SNDCTL_DSP_SPEED, &srate)) {
 92         perror("ioctl SNDCTL_DSP_SPEED");
 93         exit(1);
 94     }
 95     /* accept +/- 1% */
 96     if (srate < rate *  99 / 100 ||
 97         srate > rate * 101 / 100) {
 98         fprintf(stderr,"can't set sample rate to %d (got %d)\n",
 99                 rate,srate);
100         exit(1);
101     }
102 
103     /* get block size */
104     if (-1 == ioctl(sound_fd, SNDCTL_DSP_GETBLKSIZE,  &sound_blksize)) {
105         perror("ioctl SNDCTL_DSP_GETBLKSIZE");
106         exit(1);
107     }
108     if (0 == sound_blksize)
109         sound_blksize = 4096;
110     sound_buffer = malloc(sound_blksize);
111 
112     /* peak level history */
113     histn = peak_seconds * rate * 4 / sound_blksize;
114     histl = malloc(histn * sizeof(int));
115     histr = malloc(histn * sizeof(int));
116     memset(histl,0,histn * sizeof(int));
117     memset(histr,0,histn * sizeof(int));
118 
119     /* trigger record */
120     trigger = ~PCM_ENABLE_INPUT;
121     ioctl(sound_fd,SNDCTL_DSP_SETTRIGGER,&trigger);
122     trigger = PCM_ENABLE_INPUT;
123     ioctl(sound_fd,SNDCTL_DSP_SETTRIGGER,&trigger);
124 
125     return sound_fd;
126 }
127 
128 static int
129 sound_read(void)
130 {
131     unsigned int have;
132     int     i,rc;
133     int16_t *v;
134 
135     /* read */
136     for (have = 0;have < sound_blksize;) {
137         rc = read(sound_fd,sound_buffer+have,sound_blksize-have);
138         switch (rc) {
139         case -1:
140             if (EINTR != errno) {
141                 perror("read sound");
142                 exit(1);
143             }
144             break;
145         case 0:
146             fprintf(stderr,"Huh? got 0 bytes from sound device?\n");
147             exit(1);
148         default:
149             have += rc;
150 
151         }
152     }
153 
154     /* look for peaks */
155     maxl = 0;
156     maxr = 0;
157     for (i = sound_blksize>>2, v=sound_buffer; i > 0; i--) {
158         if (abs(*v) > maxl)
159             maxl = abs(*v);
160         v++;
161         if (abs(*v) > maxr)
162             maxr = abs(*v);
163         v++;    
164     }
165 
166     /* max for the last second */
167     histl[histi] = maxl;
168     histr[histi] = maxr;
169     histi++;
170     if (histn == histi)
171         histi = 0;
172 
173     for (secl = 0, secr = 0, i = 0; i < histn; i++) {
174         if (secl < histl[i])
175             secl = histl[i];
176         if (secr < histr[i])
177             secr = histr[i];
178     }
179     sound_rcount++;
180     return 0;
181 }
182 
183 /* -------------------------------------------------------------------- */
184 
185 char *names[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES;
186 char *config_names[SOUND_MIXER_NRDEVICES][4];
187 
188 static int  mix;
189 static int  dev = -1;
190 static int  volume;
191 static char *mixer_dev = "/dev/mixer";
192 
193 static int
194 mixer_open(char *filename, char *device)
195 {
196     int i, devmask;
197 
198     if (-1 == (mix = open(filename,O_RDONLY))) {
199         fprintf(stderr,"open %s: %s\n",filename,strerror(errno));
200         exit(1);
201     }
202     if (-1 == ioctl(mix,MIXER_READ(SOUND_MIXER_DEVMASK),&devmask)) {
203         perror("mixer read devmask");
204         exit(1);
205     }
206     for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
207         if ((1<<i) & devmask && strcasecmp(names[i],device) == 0) {
208             if (-1 == ioctl(mix,MIXER_READ(i),&volume)) {
209                 perror("mixer read volume");
210                 exit(1);
211             } else {
212                 dev = i;
213             }
214         }
215     }
216     if (-1 == dev) {
217         fprintf(stderr,"mixer: havn't found device '%s'\nmixer: available: ",device);
218         for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
219             if ((1<<i) & devmask)
220                 fprintf(stderr," '%s'",names[i]);
221         fprintf(stderr,"\n");
222         exit(1);
223     }
224     return (-1 != dev) ? 0 : -1;
225 }
226 
227 static void
228 mixer_close(void)
229 {
230     close(mix);
231     dev = -1;
232 }
233 
234 static int
235 mixer_get_volume(void)
236 {
237     return (-1 == dev) ? -1 : (volume & 0x7f);
238 }
239 
240 static int
241 mixer_set_volume(int val)
242 {
243     if (-1 == dev)
244         return -1;
245     val   &= 0x7f;
246     volume = val | (val << 8);;
247     if (-1 == ioctl(mix,MIXER_WRITE(dev),&volume)) {
248         perror("mixer write volume");
249         return -1;
250     }
251     return 0;
252 }
253 
254 /* ---------------------------------------------------------------------- */
255 /* *.wav I/O stolen from cdda2wav */
256 
257 /* Copyright (C) by Heiko Eissfeldt */
258 
259 typedef uint8_t   BYTE;
260 typedef uint16_t  WORD;
261 typedef uint32_t  DWORD;
262 typedef uint32_t  FOURCC;       /* a four character code */
263 
264 /* flags for 'wFormatTag' field of WAVEFORMAT */
265 #define WAVE_FORMAT_PCM 1
266 
267 /* MMIO macros */
268 #define mmioFOURCC(ch0, ch1, ch2, ch3) \
269   ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
270   ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24))
271 
272 #define FOURCC_RIFF     mmioFOURCC ('R', 'I', 'F', 'F')
273 #define FOURCC_LIST     mmioFOURCC ('L', 'I', 'S', 'T')
274 #define FOURCC_WAVE     mmioFOURCC ('W', 'A', 'V', 'E')
275 #define FOURCC_FMT      mmioFOURCC ('f', 'm', 't', ' ')
276 #define FOURCC_DATA     mmioFOURCC ('d', 'a', 't', 'a')
277 
278 typedef struct CHUNKHDR {
279     FOURCC ckid;                /* chunk ID */
280     DWORD dwSize;               /* chunk size */
281 } CHUNKHDR;
282 
283 /* simplified Header for standard WAV files */
284 typedef struct WAVEHDR {
285     CHUNKHDR chkRiff;
286     FOURCC fccWave;
287     CHUNKHDR chkFmt;
288     WORD wFormatTag;       /* format type */
289     WORD nChannels;        /* number of channels (i.e. mono, stereo, etc.) */
290     DWORD nSamplesPerSec;  /* sample rate */
291     DWORD nAvgBytesPerSec; /* for buffer estimation */
292     WORD nBlockAlign;      /* block size of data */
293     WORD wBitsPerSample;
294     CHUNKHDR chkData;
295 } WAVEHDR;
296 
297 #define IS_STD_WAV_HEADER(waveHdr) ( \
298   waveHdr.chkRiff.ckid == FOURCC_RIFF && \
299   waveHdr.fccWave == FOURCC_WAVE && \
300   waveHdr.chkFmt.ckid == FOURCC_FMT && \
301   waveHdr.chkData.ckid == FOURCC_DATA && \
302   waveHdr.wFormatTag == WAVE_FORMAT_PCM)
303 
304 #define cpu_to_le32(x) (x)
305 #define cpu_to_le16(x) (x)
306 #define le32_to_cpu(x) (x)
307 #define le16_to_cpu(x) (x)
308 
309 /* -------------------------------------------------------------------- */
310 
311 static WAVEHDR  fileheader;
312 static size_t   wav_size;
313 static size_t   done_size;
314 
315 static void
316 wav_init_header(int rate)
317 {
318     /* stolen from cdda2wav */
319     int nBitsPerSample = 16;
320     int channels = 2;
321 
322     unsigned long nBlockAlign = channels * ((nBitsPerSample + 7) / 8);
323     unsigned long nAvgBytesPerSec = nBlockAlign * rate;
324     unsigned long temp = /* data length */ 0 +
325         sizeof(WAVEHDR) - sizeof(CHUNKHDR);
326 
327     fileheader.chkRiff.ckid    = cpu_to_le32(FOURCC_RIFF);
328     fileheader.fccWave         = cpu_to_le32(FOURCC_WAVE);
329     fileheader.chkFmt.ckid     = cpu_to_le32(FOURCC_FMT);
330     fileheader.chkFmt.dwSize   = cpu_to_le32(16);
331     fileheader.wFormatTag      = cpu_to_le16(WAVE_FORMAT_PCM);
332     fileheader.nChannels       = cpu_to_le16(channels);
333     fileheader.nSamplesPerSec  = cpu_to_le32(rate);
334     fileheader.nAvgBytesPerSec = cpu_to_le32(nAvgBytesPerSec);
335     fileheader.nBlockAlign     = cpu_to_le16(nBlockAlign);
336     fileheader.wBitsPerSample  = cpu_to_le16(nBitsPerSample);
337     fileheader.chkData.ckid    = cpu_to_le32(FOURCC_DATA);
338     fileheader.chkRiff.dwSize  = cpu_to_le32(temp);
339     fileheader.chkData.dwSize  = cpu_to_le32(0 /* data length */);
340 }
341 
342 static void
343 wav_start_write(int fd,int rate)
344 {
345     wav_init_header(rate);
346     lseek(fd,0,SEEK_SET);
347     write(fd,&fileheader,sizeof(WAVEHDR));
348     wav_size = 0;
349 }
350 
351 static int
352 wav_write_audio(int fd, void *data, int len)
353 {
354     int rc;
355 
356     rc = write(fd,data,len);
357     if (len == rc) {
358         wav_size += len;
359         return 0;
360     } else
361         return -1;
362 }
363 
364 static void
365 wav_stop_write(int fd)
366 {
367     unsigned long temp = wav_size + sizeof(WAVEHDR) - sizeof(CHUNKHDR);
368 
369     fileheader.chkRiff.dwSize = cpu_to_le32(temp);
370     fileheader.chkData.dwSize = cpu_to_le32(wav_size);
371     lseek(fd,0,SEEK_SET);
372     write(fd,&fileheader,sizeof(WAVEHDR));
373     done_size += wav_size;
374 }
375 
376 /* -------------------------------------------------------------------- */
377 
378 static char full[] =
379 "##################################################"
380 "##################################################"
381 "##################################################"
382 "##################################################";
383 
384 static char empty[] =
385 "--------------------------------------------------"
386 "--------------------------------------------------"
387 "--------------------------------------------------"
388 "--------------------------------------------------";
389 
390 static char blank[] =
391 "                                                  "
392 "                                                  "
393 "                                                  "
394 "                                                  ";
395 
396 static char alive[] = "-\\|/";
397 //static char alive[] = ".oOo";
398 #define ALIVE(count)  alive[count % (sizeof(alive)/sizeof(alive[0])-1)]
399 
400 static void
401 print_bar(int line, char *name, int val1, int val2, int max)
402 {
403     int total,len;
404     
405     total = COLS-16;
406     len   = val1*total/max;
407 
408     mvprintw(line,0,"%-6s: %5d  ",name,(val2 != -1) ? val2 : val1);
409     printw("%*.*s",len,len,full);
410     printw("%*.*s",total-len,total-len,empty);
411     if (val2 != -1)
412         mvprintw(line,14+val2*total/max,"|");
413 }
414 
415 /* -------------------------------------------------------------------- */
416 
417 enum MODE {
418     NCURSES = 1,
419     CONSOLE = 2,
420 };
421 enum MODE mode = NCURSES;
422 int       stop,verbose;
423 char      *filename = "record";
424 int       rate = 44100;
425 
426 static void
427 ctrlc(int signal)
428 {
429     if (verbose)
430         fprintf(stderr,"\n%s - exiting\n",
431                 sys_siglist[signal]);
432     stop = 1;
433 }
434 
435 static int
436 record_start(char *outfile, int *nr)
437 {
438     int wav;
439     
440     do {
441         sprintf(outfile,"%s%03d.wav",filename,(*nr)++);
442         wav = open(outfile, O_WRONLY | O_EXCL | O_CREAT, 0666);
443     } while ((-1 == wav) && (EEXIST == errno));
444     if (-1 == wav) {
445         perror("open");
446         exit(1);
447     }
448     wav_start_write(wav,rate);
449     return wav;
450 }
451 
452 static void
453 record_stop(int fd)
454 {
455     wav_stop_write(fd);
456     close(fd);
457     switch (mode) {
458     case CONSOLE:
459         if (verbose)
460             printf("\n");
461         break;
462     case NCURSES:
463         mvprintw(3,0,"%*.*s",COLS-1,COLS-1,blank);
464         break;
465     }
466 }
467 
468 static size_t
469 parse_size(const char *arg)
470 {
471     int value;
472     char mul[4];
473     off_t retval = -1;
474 
475     if (2 != sscanf(arg,"%d%3s",&value,mul))
476         return 0;
477     if (0 == strcasecmp(mul,"g") ||
478         0 == strcasecmp(mul,"gb"))
479         retval = (off_t)value * 1024 * 1024 * 1024;
480     if (0 == strcasecmp(mul,"m") ||
481         0 == strcasecmp(mul,"mb"))
482         retval = (off_t)value * 1024 * 1024;
483     if (0 == strcasecmp(mul,"k") ||
484         0 == strcasecmp(mul,"kb"))
485         retval = (off_t)value * 1024;
486     return retval;
487 }
488 
489 static char*
490 str_mb(off_t value)
491 {
492     static char buf[32];
493 
494     if (value > (1 << 30)) {
495         value = (value * 10) >> 30;
496         sprintf(buf,"%d.%d GB",(int)(value/10),(int)(value%10));
497         return buf;
498     }
499     if (value > (1 << 20)) {
500         value = (value * 10) >> 20;
501         sprintf(buf,"%d.%d MB",(int)(value/10),(int)(value%10));
502         return buf;
503     }
504     value >>= 10;
505     sprintf(buf,"%3d kB",(int)value);
506     return buf;
507 }
508 
509 /* -------------------------------------------------------------------- */
510 
511 char      *progname;
512 char      *input = "line";
513 char      *str_maxsize = "2GB";
514 int       level_trigger;
515 
516 static void
517 usage(FILE *fp)
518 {
519     fprintf(fp,
520             "\n"
521             "%s records sound in CD-Quality (44100/16bit/stereo).\n"
522             "It has a nice ascii-art input-level meter.  It is a\n"
523             "interactive curses application.  You'll need a fast\n"
524             "terminal, don't try this on a 9600 bps vt100...\n"
525             "\n"
526             "%s has several options:\n"
527             "  -h        this text\n"
528             "  -o file   output file basename [%s], a number and the .wav\n"
529             "            extention are added by %s.\n"
530             "  -i ctrl   mixer control [%s].  This should be the one\n"
531             "            where you can adjust the record level for\n"
532             "            your audio source, \"line\", \"mic\" and \"igain\"\n"
533             "            are good candidates.\n"
534             "  -m dev    set mixer device [%s]\n"
535             "  -d dev    set dsp device   [%s]\n"
536             "  -r rate   set sample rate  [%d]\n"
537             "  -p sec    peak seconds     [%.1f]\n"
538             "\n"
539             "for non-interactive usage only:\n"
540             "  -c        enable console (non-interactive) mode\n"
541             "  -v        be verbose (show progress)\n"
542             "  -t mm:ss  limit the time to record.  By default it records\n"
543             "            until stopped by a signal (^C)\n"
544             "  -s size   set max file size [%s]. You have to give number\n"
545             "            and unit without space inbetween, i.e. \"100mb\".\n"
546             "  -n num    limit amount of files recorded, quits when\n"
547             "            reached.\n"
548             "  -l        signal level triggered recording.\n"
549             "  -L level  same as above + specify trigger level [%d]\n"
550             "\n",
551             progname,progname,filename,progname,
552             input,mixer_dev,audio_dev,
553             rate,peak_seconds,str_maxsize,
554             level_trigger ? level_trigger : 1000);
555 }
556 
557 int
558 main(int argc, char *argv[])
559 {
560     int             c,key,vol,delay,auto_adjust;
561     int             record,nr,wav=0;
562     char            *outfile;
563     fd_set          s;
564     int             sec,maxhour,maxmin,maxsec;
565     int             maxfiles = 0;
566     size_t          maxsize;
567 
568     /* init some vars */
569     progname = strrchr(argv[0],'/');
570     progname = progname ? progname+1 : argv[0];
571     maxsec  = 0;
572     delay   = 0;
573     auto_adjust   = 1;
574     record = 0;
575     nr = 0;
576 
577     /* parse options */
578     for (;;) {
579         if (-1 == (c = getopt(argc, argv, "vhlci:o:d:m:r:t:s:L:p:n:")))
580             break;
581         switch (c) {
582         case 'v':
583             verbose = 1;
584             break;
585         case 'l':
586             level_trigger = 1000;
587             break;
588         case 'L':
589             level_trigger = atoi(optarg);
590             break;
591         case 'i':
592             input = optarg;
593             break;
594         case 'o':
595             filename = optarg;
596             break;
597         case 'd':
598             audio_dev = optarg;
599             break;
600         case 'm':
601             mixer_dev = optarg;
602             break;
603         case 'c':
604             mode = CONSOLE;
605             break;
606         case 'r':
607             rate = atoi(optarg);
608             break;
609         case 'p':
610             peak_seconds = atof(optarg);
611             break;
612         case 't':
613             if (3 != sscanf(optarg,"%d:%d:%d",&maxhour,&maxmin,&maxsec)) {
614                 maxhour = 0;
615                 if (2 != sscanf(optarg,"%d:%d",&maxmin,&maxsec)) {
616                     fprintf(stderr,"time parse error\n");
617                     exit(1);
618                 }
619             }
620             maxsec += maxmin  * 60;
621             maxsec += maxhour * 60 * 60;
622             break;
623         case 's':
624             str_maxsize = optarg;
625             break;
626         case 'n':
627             maxfiles = atoi(optarg);
628             break;
629         case 'h':
630             usage(stdout);
631             exit(0);
632         default:
633             usage(stderr);
634             exit(1);
635         }
636     }
637     maxsize = parse_size(str_maxsize);
638     if (0 == maxsize) {
639         fprintf(stderr,"maxsize parse error [%s]\n",str_maxsize);
640         exit(1);
641     }
642 
643     mixer_open(mixer_dev,input);
644     sound_open(rate);
645     outfile = malloc(strlen(filename)+16);
646 
647     if (mode == NCURSES) {
648         tty_raw();
649         atexit(tty_restore);
650     }
651 
652     signal(SIGINT,ctrlc);
653     signal(SIGQUIT,ctrlc);
654     signal(SIGTERM,ctrlc);
655     signal(SIGHUP,ctrlc);
656 
657     if (mode == NCURSES) {
658         mvprintw( 5,0,"record to   %s*.wav",filename);
659         mvprintw( 7,0,"left/right  adjust mixer level for \"%s\"",input);
660         mvprintw( 8,0,"space       starts/stops recording");
661         /* line 9 is printed later */
662         mvprintw(10,0,"            auto-adjust reduces the record level on overruns");
663         mvprintw(11,0,"'N'         next file (same as space twice, but without break)");
664         mvprintw(12,0,"'Q'         quit");
665         mvprintw(LINES-3,0,"--");
666         mvprintw(LINES-2,0,"(c) 1999-2003 Gerd Knorr <kraxel@bytesex.org>");
667         
668         for (;!stop;) {
669             refresh();
670             FD_ZERO(&s);
671             FD_SET(0,&s);
672             FD_SET(sound_fd,&s);
673             if (-1 == select(sound_fd+1,&s,NULL,NULL,NULL)) {
674                 if (EINTR == errno)
675                     continue;
676                 perror("select");
677                 break;
678             }
679             
680             if (FD_ISSET(sound_fd,&s)) {
681                 /* sound */
682                 if (-1 == sound_read())
683                     break;
684                 if (delay)
685                     delay--;
686                 if (auto_adjust && (0 == delay) &&
687                     (maxl >= 32767 || maxr >= 32767)) {
688                     /* auto-adjust */
689                     vol = mixer_get_volume();
690                     vol--;
691                     if (vol < 0)
692                         vol = 0;
693                     mixer_set_volume(vol);
694                     delay = 3;
695                 }
696                 print_bar(0,input,mixer_get_volume(),-1,100);
697                 print_bar(1,"left",maxl,secl,32768);
698                 print_bar(2,"right",maxr,secr,32768);
699                 mvprintw(9,0,"'A'         toggle auto-adjust [%s] ",
700                          auto_adjust ? "on" : "off");
701                 if (record) {
702                     wav_write_audio(wav,sound_buffer,sound_blksize);
703                     sec = wav_size / (rate*4);
704                     mvprintw(3,0,"%s: %3d:%02d (%s) ",outfile,
705                              sec/60,sec%60,str_mb(wav_size));
706                 } else {
707                     mvprintw(3,0,"%c",ALIVE(sound_rcount));
708                 }
709             }
710             
711             if (FD_ISSET(0,&s)) {
712                 /* tty in */
713                 switch (key = getch()) {
714                 case 'Q':
715                 case 'q':
716                     stop = 1;
717                     break;
718                 case 'A':
719                 case 'a':
720                     auto_adjust = !auto_adjust;
721                     break;
722                 case 'N':
723                 case 'n':
724                     if (record) {
725                         record_stop(wav);
726                         wav = record_start(outfile,&nr);
727                     }
728                     break;
729                 case ' ':
730                     if (!filename)
731                         break;
732                     if (!record) {
733                         /* start */
734                         wav = record_start(outfile,&nr);
735                         record=1;
736                         auto_adjust=0;
737                     } else {
738                         /* stop */
739                         record_stop(wav);
740                         record=0;
741                     }
742                     break;
743                 case KEY_RIGHT:
744                     vol = mixer_get_volume();
745                     vol++;
746                     if (vol > 100)
747                         vol = 100;
748                     mixer_set_volume(vol);
749                     break;
750                 case KEY_LEFT:
751                     vol = mixer_get_volume();
752                     vol--;
753                     if (vol < 0)
754                         vol = 0;
755                     mixer_set_volume(vol);
756                     break;
757                 }
758             }
759         }
760     }
761 
762     if (mode == CONSOLE) {
763         if (!level_trigger) {
764             wav = record_start(outfile,&nr);
765             record=1;
766         }
767 
768         for (;!stop;) {
769             if (-1 == sound_read())
770                 break;
771             if (level_trigger) {
772                 if (!record &&
773                     (maxl > level_trigger ||
774                      maxr > level_trigger)) {
775                     wav = record_start(outfile,&nr);
776                     record=1;
777                 }
778                 if (record &&
779                     secl < level_trigger &&
780                     secr < level_trigger) {
781                     record_stop(wav);
782                     record=0;
783                     if (maxfiles && nr == maxfiles)
784                         break;
785                 }
786             }
787             if (!record) {
788                 printf("waiting for signal %c [%d/%d]...  \r",
789                        ALIVE(sound_rcount), maxl,maxr);
790                 fflush(stdout);
791                 continue;
792             }
793 
794             sec = (done_size + wav_size) / (rate*4);
795             if (maxsec && sec >= maxsec)
796                 break;
797             if (wav_size + sound_blksize + sizeof(WAVEHDR) > maxsize) {
798                 record_stop(wav);
799                 wav = record_start(outfile,&nr);
800             }
801             wav_write_audio(wav,sound_buffer,sound_blksize);
802             if (verbose) {
803                 int total = 10;
804                 int len   = (maxl+maxr)*total/32768/2;
805                 printf("|%*.*s%*.*s|  %s  %d:%02d",
806                        len,len,full, total-len,total-len,empty,
807                        outfile,sec/60,sec%60);
808                 if (maxsec)
809                     printf("/%d:%02d",maxsec/60,maxsec%60);
810                 printf(" (%s",str_mb(wav_size));
811                 if (done_size)
812                     printf(", %s total",str_mb(done_size + wav_size));
813                 printf(")      \r");
814                 fflush(stdout);
815             }
816         }
817     }
818     
819     if (record)
820         record_stop(wav);
821     mixer_close();
822     exit(0);
823 }
824 
  This page was automatically generated by the LXR engine.