/* * XmNap A Motif napster client * * Copyright (C) 2000 Mats Peterson * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * Please send any comments/bug reports to * mats_peterson@swipnet.se (Mats Peterson) */ #ifdef USE_SOUND #include #include #include #include #include #include #include #include #include #include #include "msgbox.h" #include "sound.h" #include "util.h" String sound[NUM_SOUNDS]; WAVHDR* ReadWavHdr(int fd) { static WAVHDR *wavHdr = NULL; if (! wavHdr) wavHdr = (WAVHDR*)XtMalloc(sizeof(WAVHDR)); if (read(fd, wavHdr, sizeof(WAVHDR)) == -1) return NULL; wavHdr->riffTag = BSWAP32(wavHdr->riffTag); wavHdr->riffLength = BSWAP32(wavHdr->riffLength); wavHdr->waveTag = BSWAP32(wavHdr->waveTag); wavHdr->fmtTag = BSWAP32(wavHdr->fmtTag); wavHdr->fmtLength = BSWAP32(wavHdr->fmtLength); wavHdr->format = BSWAP16(wavHdr->format); wavHdr->channels = BSWAP16(wavHdr->channels); wavHdr->sampRate = BSWAP32(wavHdr->sampRate); wavHdr->avgSampRate = BSWAP32(wavHdr->avgSampRate); wavHdr->align = BSWAP16(wavHdr->align); wavHdr->bitsPerSample = BSWAP16(wavHdr->bitsPerSample); wavHdr->dataTag = BSWAP32(wavHdr->dataTag); wavHdr->dataLength = BSWAP32(wavHdr->dataLength); return wavHdr; } int CheckWav(String name) { WAVHDR *wavHdr; int fd = 0, retVal = 0; char tmp[128]; if ((fd = open(name, O_RDONLY)) == -1) { ErrMsg(strerror(errno)); goto error; } if (! (wavHdr = ReadWavHdr(fd))) { ErrMsg(strerror(errno)); goto error; } if ((wavHdr->riffTag != RIFF) || (wavHdr->waveTag != WAVE) || (wavHdr->fmtTag != FMT) || (wavHdr->dataTag != DATA)) { ErrMsg("Invalid WAV format"); goto error; } if (wavHdr->format != PCM_CODE) { ErrMsg("Can't play not PCM-coded WAV files"); goto error; } if (wavHdr->channels > 2) { sprintf(tmp, "Can't play WAV files with %d channels", wavHdr->channels); ErrMsg(tmp); goto error; } goto exit; error: retVal = -1; exit: if (fd > 0) close(fd); return retVal; } void PlaySound(String name) { WAVHDR *wavHdr; char tmp[256]; char *audioBuf = NULL; int fd = 0, audio = 0, bufSize, sampleSize, stereo, speed, toRead, n; static int pid = 0; int pid2; if (! strlen(name)) return; if (pid) { if ((pid2 = waitpid(pid, NULL, WNOHANG | WUNTRACED)) <= 0) { if (pid2 == -1) { sprintf(tmp, "waitpid: %s", strerror(errno)); ErrMsg(tmp); } return; } } pid = fork(); if (pid == 0) { if ((audio = open("/dev/dsp", O_WRONLY)) == -1) goto exit; if ((fd = open(name, O_RDONLY)) == -1) goto exit; if (! (wavHdr = ReadWavHdr(fd))) goto exit; if (ioctl(audio, SNDCTL_DSP_GETBLKSIZE, &bufSize) == -1) goto exit; audioBuf = XtMalloc(bufSize); sampleSize = (int)wavHdr->bitsPerSample; stereo = (wavHdr->channels == 2) ? 1 : 0; speed = (int)wavHdr->sampRate; if (ioctl(audio, SNDCTL_DSP_SAMPLESIZE, &sampleSize) == -1) goto exit; if (ioctl(audio, SNDCTL_DSP_STEREO, &stereo) == -1) goto exit; if (ioctl(audio, SNDCTL_DSP_SPEED, &speed) == -1) goto exit; toRead = wavHdr->dataLength; while (toRead) { n = (toRead > bufSize) ? bufSize : toRead; if (read(fd, audioBuf, n) == -1) break; if (write(audio, audioBuf, n) == -1) break; toRead -= n; } exit: if (audio > 0) close(audio); if (fd > 0) close(fd); if (audioBuf) XtFree(audioBuf); _exit(0); } else if (pid < 0) { sprintf(tmp, "fork: %s", strerror(errno)); ErrMsg(tmp); } } #endif .