📄 wavplay.c
字号:
/* wavplay.c 30.05.99 tn simple wavfile-player. plays only 44.1khz,16bit,stereo files. gui-mode to fully control all play-functions via external interface works fine on little and big endian machines.*/#include <stdio.h>#include <sys/types.h>#include <stdlib.h>#include <unistd.h>#include <fcntl.h>#include <string.h>#if defined(linux) || defined(__CYGWIN32__)#include <getopt.h>#endif#include <sys/stat.h>#ifdef linux#include <sys/soundcard.h>#include <sys/ioctl.h>#endif#ifdef sun #include <sys/audioio.h>#endif#ifdef hpux#include <sys/audio.h>#endif#include <glib.h>#include "xcdroast.h"gint read_line(gint fd, gchar *ptr, gint maxlen);gint is_std_wav_file(guchar *hdr);gint is_in_cd_quality(guchar *hdr);guchar waveHdr[44];gint abuf_size;gchar *audiobuf;#ifdef linux #define DEFAULT_AUDIO_DEVICE "/dev/dsp"#else#define DEFAULT_AUDIO_DEVICE "/dev/audio"#endif#define DEFAULT_BUFFER_SIZE 32768#ifdef linux/* open the sound-device of linux and set cd-quality */gint open_linux_audio(gchar *dev) {gint audio;gint tmp;gint samplesize = 16;gint dsp_stereo = 1;gint dsp_speed = 44100;gint flags; /* First try open with O_NONBLOCK so it doesn't hang */ audio = open (dev, (O_WRONLY | O_NONBLOCK),0); if (audio == -1) { /* error opening sound device */ return -1; } /* now undo NONBLOCK setting again */ flags = fcntl(audio,F_GETFL); fcntl(audio,F_SETFL,flags & ~O_NONBLOCK); tmp = samplesize; ioctl(audio, SNDCTL_DSP_SAMPLESIZE, &samplesize); if (tmp != samplesize) { /* error setting samplesize */ g_warning("Unable to set samplesize to 16 bit\n"); return -1; } if (ioctl (audio, SNDCTL_DSP_STEREO, &dsp_stereo)==-1) { g_warning("Unable to set audio to stereo\n"); return -1; } if (ioctl (audio, SNDCTL_DSP_SPEED, &dsp_speed) == -1) { g_warning("Unable to set audio to 44.1 kHz\n"); return -1; } if (ioctl (audio, SNDCTL_DSP_GETBLKSIZE, &abuf_size) == -1) { g_warning("Unable to get blocksize for audio-device\n"); return -1; } return audio;}#endif#ifdef sun/* open the sound-device of solaris and set cd-quality */gint open_solaris_audio(gchar *dev) {gint audio;audio_info_t info;gint flags; /* First try open with O_NONBLOCK so it doesn't hang */ if ((audio = open(dev, (O_WRONLY | O_NONBLOCK))) == -1) { /* error opening sound device */ return -1; } /* now undo NONBLOCK setting again */ flags = fcntl(audio,F_GETFL); fcntl(audio,F_SETFL,flags & ~O_NONBLOCK); abuf_size = DEFAULT_BUFFER_SIZE; AUDIO_INITINFO(&info); info.play.sample_rate = 44100; info.play.channels = 2; info.play.precision = 16; info.play.encoding = AUDIO_ENCODING_LINEAR; info.play.buffer_size = abuf_size; info.output_muted = 0; if (ioctl(audio, AUDIO_SETINFO, &info) == -1) { g_warning("Unable to set audio parameters\n"); return -1; } return audio;}#endif#ifdef hpux/* open the sound-device of hp-ux and set cd-quality */gint open_hpux_audio(gchar *dev) {struct audio_limits alimits;gint audio; audio = open (dev, O_WRONLY,0); if (audio == -1) { /* error opening sound device */ return -1; } if (ioctl(audio, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_LINEAR16BIT) == -1) { g_warning("Unable to set samplesize to 16 bit\n"); return -1; } if (ioctl (audio, AUDIO_SET_CHANNELS, 2)==-1) { g_warning("Unable to set audio to stereo\n"); return -1; } if (ioctl (audio, AUDIO_SET_SAMPLE_RATE, 44100) == -1) { g_warning("Unable to set audio to 44.1 kHz\n"); return -1; } if (ioctl(audio,AUDIO_GET_LIMITS,&alimits) == -1) { g_warning("Unable to get blocksize for audio-device\n"); return -1; } abuf_size = alimits.max_transmit_buffer_size; return audio;}#endif/* print usage info */void usage(gchar *cmd) { g_print("Usage: %s [options] filename (Version: %s)\n", cmd, XCDROAST_VERSION); g_print("Options:\n"); g_print(" -d audio-device\n"); g_print(" -g : gui-mode\n"); g_print(" -q : quiet-mode\n");}/* main programm */gint main(gint argc, gchar **argv) {gint c;gchar audio_dev[MAXLINE];gchar wavname[MAXLINE];gint audio = -1;gint fd;gint l,ii;gint guimode = 0;gint quiet = 0;gint doplay = 1;gint tick = 0;gint oldtick = 0;glong bytessofar = 0;glong totalbytes;struct stat stat_buf;gint min,sec;gchar keybuffer[MAXLINE];gchar tmpswap; /* if no device given, set default device */ strcpy(audio_dev,DEFAULT_AUDIO_DEVICE); strcpy(wavname,""); while ((c = getopt(argc, argv, "d:gq")) != EOF) switch ((gchar)c) { case 'd': strncpy(audio_dev,optarg,MAXLINE); break; case 'g': guimode = 1; quiet = 1; break; case 'q': quiet = 1; break; default: usage(argv[0]); exit(1); } /* additional parameter given? */ if (optind > argc -1) { usage(argv[0]); exit(1); } else { strncpy(wavname,argv[optind++],MAXLINE); } /* this sets also the global abuf_size-variable */#ifdef linux audio = open_linux_audio(audio_dev);#endif#ifdef sun audio = open_solaris_audio(audio_dev);#endif#ifdef hpux audio = open_hpux_audio(audio_dev);#endif if (audio == -1) { g_warning("Can't init sound-system\n"); exit(1); } if ((audiobuf = (gchar *)g_new(gchar *,abuf_size)) == NULL) { g_warning("Unable to allocate audio-buffer\n"); exit(1); } /* open wavfile */ fd = open (wavname, O_RDONLY, 0); if (fd == -1) { close(audio); g_warning("Can't open wav-file\n"); exit(1); } /* get filesize */ fstat(fd, &stat_buf); totalbytes = (glong) (stat_buf.st_size - sizeof(waveHdr)); read(fd, &waveHdr, sizeof(waveHdr)); /* is it a wav-file? */ if (!is_std_wav_file(waveHdr)) { g_warning("No valid wavfile\n"); exit(0); } /* is it in cd-quality? */ if (!is_in_cd_quality(waveHdr)) { g_warning("wavfile not in cd-quality\n"); exit(0); } if (!quiet) { min = (gint) (totalbytes/(CDDAFRAME*75*60)); sec = (gint) ((totalbytes/CDDAFRAME) % (60*75))/75; g_print("Playing: %s [%d:%02d]\n", wavname, min,sec); } if (guimode) { /* in gui-mode we communicate via stdin and stdout */ /* stdin must be nonblocking */ fcntl(STDIN_FILENO,F_SETFL,O_NONBLOCK); /* update display */ g_print("secs%d\n",(gint) (totalbytes/CDDAFRAME)/75); fflush(stdout); } /* ok..all set now, start playing */ while (1) { /* guimode: look for commands from stdin */ if (guimode && (read_line(STDIN_FILENO,keybuffer,MAXLINE) > 0)) { /* stop command */ if (g_strncasecmp(keybuffer,"stop",4) == 0) { lseek(fd, sizeof(waveHdr), SEEK_SET); bytessofar = 0; tick = 0; doplay = 0; g_print("stop0\n"); fflush(stdout); } /* play command */ if (g_strncasecmp(keybuffer,"play",4) == 0) { doplay = 1; } /* pause command */ if (g_strncasecmp(keybuffer,"pause",5) == 0) { doplay=1-doplay; g_print("%s%d\n",doplay?"play":"stop",tick); fflush(stdout); } /* setxxx command */ if (g_strncasecmp(keybuffer,"set",3) == 0) { tick = atoi(keybuffer+3); bytessofar = (glong) (tick*CDDAFRAME*75); lseek(fd, sizeof(waveHdr)+bytessofar, SEEK_SET); g_print("%s%d\n",doplay?"play":"stop",tick); fflush(stdout); } /* quit command */ if (g_strncasecmp(keybuffer,"quit",4) == 0) { break; } } /* we are in play mode right now */ if (doplay) { /* read from wav-file */ l = read(fd, audiobuf, abuf_size); if (l > 0) { if (G_BYTE_ORDER == G_BIG_ENDIAN) { /* turn endian-ness */ for (ii=0; ii<l; ii+=2) { tmpswap=audiobuf[ii]; audiobuf[ii]=audiobuf[ii+1]; audiobuf[ii+1]=tmpswap; } } if (guimode) { /* at which second are we right now? */ tick=(gint)(bytessofar/CDDAFRAME/75); if (tick != oldtick) { g_print("play%d\n",tick); fflush(stdout); oldtick = tick; } } if (write(audio, audiobuf, l) != l) { g_print("write error to audio-device\n"); exit(-1); } bytessofar+=abuf_size; } else { /* read error on wav-file */ if (l == -1) { g_print("read error on wav-file\n"); exit(-1); } /* EOF reached */ doplay = 0; if (guimode) { /* roll back */ lseek(fd, sizeof(waveHdr), SEEK_SET); bytessofar = 0; tick = 0; g_print("done%d\n",tick); fflush(stdout); } else { break; } } } else { /* we are in pause-mode */ /* wait a short while and then look for commands again */ usleep(100); } } close(fd); close(audio); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -