/*
* 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
*
[email protected] (Mats Peterson)
*/
#ifdef USE_SOUND
#include <Xm/Xm.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <sys/soundcard.h>
#include <errno.h>
#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