/*
* Copyright (c) 1994,1995 Dimitrios P. Bouras and William K. W. Cheung
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of the X Consortium shall not be
* used in advertising or otherwise to promote the sale, use or other dealings
* in this Software without prior written authorization from the X Consortium.
*
* Derived from the MIT X11R5 xbiff, written by Jim Fulton, which is
* copyrighted (c) 1988 X Consortium.
*
* Mailbox XPM additions-modifications: Dimitrios P. Bouras
* Audio support and XPM icon animation: William K. W. Cheung
* Derived from xmailbox by Dimitrios P. Bouras and William K. W. Cheung
* as well as volume by Sam Lantinga. The above copyright notice is
* from Dimitros and William's file Mailbox.c in the xmailbox application.
* modified and integrated into Coolmail: Randall K. Sharpe */
#include <sys/stat.h> /* for stat() ** needs types.h ***/
#include <sys/signal.h> /* for signal() */
#include <stdio.h> /* for printing error messages */
#include <pwd.h> /* for getting username */
#include <stdlib.h> /* for getenv() */
#include <string.h>
#include <sys/file.h>
#include <sys/fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>
extern int cool_vol;
extern char *sndfile;
/* I am only doing sun audio -- RKS */
/* Adapted from <multimedia/audio_filehdr.h> */
typedef unsigned u_32; /* we assume sizeof(unsigned) = 4 */
typedef struct {
u_32 magic; /* magic number */
u_32 hdr_size; /* size of this header */
u_32 data_size; /* length of data (optional) */
u_32 encoding; /* data encoding format */
u_32 sample_rate; /* samples per second */
u_32 channels; /* number of interleaved channels */
} Audio_filehdr;
#ifdef linux
#include <linux/soundcard.h>
#define DEV_MIXER "/dev/mixer"
#define MAX_VOLUME 100
#define MIN_VOLUME 1
#define RIGHT 0x01
#define LEFT 0x02
typedef struct stereovolume
{
unsigned char left;
unsigned char right;
unsigned char pad[2];
} StereoVolume;
void setvolume(int which, unsigned char setting, StereoVolume *volptr)
{
if ( setting < MIN_VOLUME )
setting=MIN_VOLUME;
if ( setting > MAX_VOLUME )
setting=MAX_VOLUME;
if ( which&RIGHT )
volptr->right=setting;
if ( which&LEFT )
volptr->left=setting;
}
#else
#include <sun/audioio.h>
#endif
#ifndef min
#define min(x,y) ((x) < (y)? (x): (y))
#endif
#define CLOSE_FD(afd) { if (afd > -1) close(afd); afd = -1; }
#ifdef linux
#define INIT_FD { audiofd = filefd = mixer_fd = -1; }
#define END_FD { CLOSE_FD(audiofd); CLOSE_FD(filefd); CLOSE_FD(mixer_fd); return; }
#else
#define INIT_FD { audiofd = filefd = 0; }
#define END_FD { CLOSE_FD(audiofd); CLOSE_FD(filefd); return; }
#endif
void audio_beep (void)
{
int audiofd, filefd;
int rn, wn, len;
unsigned char buf[256];
Audio_filehdr *au_hdr;
#ifdef linux
StereoVolume origVol, volume;
int mixer_fd;
#else
audio_info_t ais;
int origVol;
#endif
INIT_FD;
audiofd = open( "/dev/audio", O_WRONLY | O_NDELAY );
if (audiofd < 0) {
perror("/dev/audio");
fprintf(stderr, "%s: Problem opening /dev/audio.\n",
"Coolmail");
END_FD;
}
#ifdef linux
if ( (mixer_fd=open(DEV_MIXER, O_RDWR, 0)) < 0 ) {
fprintf(stderr, "Can't open %s: ", DEV_MIXER);
END_FD;
}
if ( ioctl(mixer_fd, MIXER_READ(SOUND_MIXER_VOLUME), &origVol) < 0 ) {
perror("Can't obtain current volume settings");
END_FD;
}
setvolume(LEFT|RIGHT, cool_vol, &volume);
if ( ioctl(mixer_fd, MIXER_WRITE(SOUND_MIXER_VOLUME), &volume) < 0 ) {
fprintf(stderr, "Can't set current volume settings");
END_FD;
}
#else
if( ioctl( audiofd, AUDIO_GETINFO, &ais ) ) {
fprintf(stderr, "%s: Problem retrieving /dev/audio info.\n",
"Coolmail");
END_FD;
}
origVol = ais.play.gain;
ais.play.gain = cool_vol;
if( ioctl( audiofd, AUDIO_SETINFO, &ais ) ) {
fprintf(stderr, "Coolmail: Error %d returned from ioctl.\n",
errno);
fprintf(stderr, "%s: Problem setting /dev/audio info.\n",
"Coolmail");
END_FD;
}
#endif
filefd = open(sndfile, O_RDONLY);
if (filefd < 0) {
fprintf(stderr, "%s: Couldn't play file \"%s\"\n",
"Coolmail", sndfile);
END_FD;
}
/* Read in the audio header */
rn = read(filefd, buf, sizeof(Audio_filehdr));
if (rn > 0 && strncmp(buf, ".snd", 4) != 0) {
fprintf(stderr, "%s: Invalid audio file format.\n",
"Coolmail");
END_FD;
}
/* Strip the header */
au_hdr = (Audio_filehdr *)buf;
#ifdef linux
rn = ntohl(au_hdr->hdr_size) - sizeof(Audio_filehdr);
#else
rn = au_hdr->hdr_size - sizeof(Audio_filehdr);
#endif
for( ; rn > 0; ) {
len = min(rn, sizeof(buf));
len = read(filefd, buf, len);
rn -= len;
}
while(1) {
rn = read(filefd, buf, sizeof(buf));
if (rn < 0) {
fprintf(stderr, "%s: Error reading from file \"%s\"\n",
"Coolmail", sndfile);
END_FD;
}
if (rn == 0)
break;
while(1) {
wn = write(audiofd, buf, rn);
if ( wn < 0 ) {
fprintf(stderr, "%s: Error writing to /dev/audio.\n",
"Coolmail");
END_FD;
}
if ( wn != 0 )
break;
usleep(1000);
}
}
#ifdef linux
CLOSE_FD(audiofd);
if ( ioctl(mixer_fd, MIXER_WRITE(SOUND_MIXER_VOLUME), &origVol) < 0 ) {
fprintf(stderr, "Can't reset volume settings");
}
CLOSE_FD(mixer_fd);
#else
ais.play.gain = origVol;
if( ioctl( audiofd, AUDIO_SETINFO, &ais ) ) {
fprintf(stderr, "%s: Problem setting /dev/audio info.\n",
"Coolmail");
}
#endif
END_FD;
return;
}
syntax highlighted by Code2HTML, v. 0.9.1