xenocara/app/xlockmore/xlock/sound.c
2006-11-26 11:07:42 +00:00

462 lines
10 KiB
C

#if !defined( lint ) && !defined( SABER )
static const char sccsid[] = "@(#)sound.c 4.00 97/01/01 xlockmore";
#endif
/*-
* sound.c - xlock.c and vms_play.c
*
* See xlock.c for copying information.
*
* Revision History:
* 26-Oct-01: Allow wild cards on sound-files. (joukj@hrem.stm.tudelft.nl)
*/
#include "xlock.h"
#include "iostuff.h"
#ifdef USE_RPLAY
#include <rplay.h>
static void
play_sound(char *filename, Bool verbose)
{
int rplay_fd = rplay_open_default();
if (rplay_fd >= 0) {
rplay_sound(rplay_fd, filename);
rplay_close(rplay_fd);
}
}
#endif
#ifdef USE_NAS
/* Gives me lots of errors when I compile nas-1.2p5 -- xlock maintainer */
/*-
* Connect each time, because it might be that the server was not running
* when xlock first started, but is when next nas_play is called
*/
#include <audio/audio.h>
#include <audio/audiolib.h>
extern Display *dsp;
static void
play_sound(char *filename, Bool verbose)
{
char *auservername = DisplayString(dsp);
char *fname = filename;
AuServer *aud; /* audio server connection */
if (!(aud = AuOpenServer(auservername, 0, NULL, 0, NULL, NULL)))
return; /*cannot connect - no server? */
/*
* now play the file at recorded volume (3rd arg is a percentage),
* synchronously
*/
AuSoundPlaySynchronousFromFile(aud, fname, 100);
AuCloseServer(aud);
}
#endif
#ifdef USE_XAUDIO
/* Anybody ever get this working? XAudio.007 */
#endif
#ifdef HAS_MMOV
#include <prvdef.h>
#include <ssdef.h>
extern void PLAY_SOUND_MMOV(char* filename, Bool verbose);
#endif
#ifdef USE_VMSPLAY
/*-
* Jouk Jansen <joukj@hrem.stm.tudelft.nl> contributed this
* which he found at http://axp616.gsi.de:8080/www/vms/mzsw.html
*
* quick hack for sounds in xlockmore on VMS
* with a the above AUDIO package slightly modified
*/
#include <file.h>
#include <unixio.h>
#include <iodef.h>
#include "vms_amd.h"
static int
play_sound_so(char *filename, Bool verbose)
{
int i, j, status;
char buffer[2048];
int volume = 65; /* volume is default to 65% */
/* use the internal speaker(s) */
int speaker = SO_INTERNAL /*SO_EXTERNAL */ ;
int fp;
status = AmdInitialize("SO:", volume); /* Initialize access to AMD */
if ( status !=0 ) return status;
AmdSelect(speaker); /* Select which speaker */
fp = open(filename, O_RDONLY, 0777); /* Open the file */
if (!(fp == -1)) {
/* Read through it */
i = read(fp, buffer, 2048);
while (i) {
status = AmdWrite(buffer, i);
if (!(status & 1))
exit(status);
i = read(fp, buffer, 1024);
}
}
(void) close(fp);
return 0;
}
#endif
#if defined( HAS_MMOV ) || defined( USE_VMSPLAY )
static void
play_sound(char* filename, Bool verbose)
{
#ifdef USE_VMSPLAY
if (play_sound_so(filename, verbose) != 0 )
#endif
{
#ifdef HAS_MMOV
int pr_status , privs[2] , SYS$SETPRV();
privs[1] = 0;
privs[0] = PRV$M_SYSNAM;
pr_status = SYS$SETPRV ( 1, privs, 0, 0 );
if ( pr_status == SS$_NORMAL ) PLAY_SOUND_MMOV(filename, verbose);
#endif
}
}
#endif
#ifdef DEF_PLAY
static void
play_sound(char *filename, Bool verbose)
{
char *progrun = NULL;
if ((progrun = (char *) malloc(strlen(DEF_PLAY) + strlen(filename) + 11)) != NULL) {
(void) sprintf(progrun, "( %s %s ) 2>&1", DEF_PLAY, filename);
/*(void) printf("%s\n", progrun); */
(void) system(progrun);
free(progrun);
}
}
#endif
#ifdef USE_ESOUND
#ifndef DEFAULT_SOUND_DIR
#if 1
#define DEFAULT_SOUND_DIR "/usr/lib/X11/xlock/sounds/"
#else
#define DEFAULT_SOUND_DIR "@PREFIX@/lib/X11/xlock/sounds/"
#endif
#endif
#ifdef HAVE_LIBESD
#include <sys/stat.h>
#include <esd.h>
#else
#error Sorry, but you cannot use ESD without ESD !!!?
#endif
typedef struct _esd_sample
{
char *file;
int rate;
int format;
int samples;
unsigned char *data;
int id;
struct _esd_sample *next;
} EsdSample_t;
typedef EsdSample_t *EsdSample_ptr;
static EsdSample_ptr EsdSamplesList =(EsdSample_ptr)NULL;
static int sound_fd = -1;
static EsdSample_ptr sound_esd_load_sample(char *file);
static void sound_esd_play(EsdSample_ptr s);
static void sound_esd_destroy_sample(EsdSample_ptr s);
static int sound_esd_init(void);
static void sound_esd_shutdown(void);
/*
* Public ESOUND sound functions
* =============================
*/
static void
play_sound(char *filename, Bool verbose)
{
#ifdef DEBUG
(void) fprintf( stderr, "play_sound %s\n", filename );
#endif
if ( filename && *filename )
sound_esd_play( sound_esd_load_sample( filename ) );
}
int init_sound(void)
{
return( sound_esd_init() );
}
void shutdown_sound(void)
{
sound_esd_shutdown();
}
/* Found this snippet from modes/glx/xpm-image.c by way of
Jamie Zawinski <jwz@jwz.org> Copyright (c) 1998 */
static Bool
bigendian (void)
{
union { int i; char c[sizeof(int)]; } u;
u.i = 1;
return !u.c[0];
}
/*
* Private ESOUND sound functions
* ==============================
*/
static EsdSample_ptr
sound_esd_load_sample(char *file)
{
AFfilehandle in_file;
struct stat stbuf;
EsdSample_ptr s;
int in_format, in_width, in_channels, frame_count;
int bytes_per_frame;
double in_rate;
char *origfile = strdup( file ? file : "" );
char fullfile[MAXPATHLEN];
#ifdef DEBUG
(void) fprintf(stderr, "sound_esd_load_sample: %s\n", origfile);
#endif
s = EsdSamplesList;
while ( s && strcmp( file, s->file ) )
s = s->next;
if ( s && !strcmp( file, s->file ) )
return s;
#ifdef DEBUG
(void) fprintf(stderr, "sound_esd_load_sample: sample not loaded: loading ...\n", origfile);
#endif
if (file[0] != '/')
{
(void) sprintf( fullfile, "%s/%s", DEFAULT_SOUND_DIR, file );
file = fullfile;
}
if (stat(file, &stbuf) < 0)
{
(void) fprintf( stderr, "Error ! Cannot find the sound file %s\n", file);
return NULL;
}
if ( !( in_file = afOpenFile(file, "r", NULL) ) )
{
(void) fprintf( stderr, "Error ! Cannot open sound sample ! Bad format ?\n" );
return(NULL);
}
s = EsdSamplesList;
if ( s )
{
while ( s && s->next )
s = s->next;
s->next = (EsdSample_t *) malloc(sizeof(EsdSample_t));
if ( !s->next )
{
(void) fprintf( stderr, "Error ! cannot allocate sample data !\n" );
(void) afCloseFile(in_file);
return NULL;
}
s = s->next;
s->next = NULL;
}
else
{
s = (EsdSample_t *) malloc(sizeof(EsdSample_t));
if ( !s )
{
(void) fprintf( stderr, "Error ! cannot allocate sample data !\n" );
(void) afCloseFile(in_file);
return NULL;
}
EsdSamplesList = s;
s->next = NULL;
}
frame_count = afGetFrameCount(in_file, AF_DEFAULT_TRACK);
in_channels = afGetChannels(in_file, AF_DEFAULT_TRACK);
in_rate = afGetRate(in_file, AF_DEFAULT_TRACK);
afGetSampleFormat(in_file, AF_DEFAULT_TRACK, &in_format, &in_width);
afSetVirtualByteOrder(in_file, AF_DEFAULT_TRACK, (bigendian()) ?
AF_BYTEORDER_BIGENDIAN : AF_BYTEORDER_LITTLEENDIAN);
s->file = strdup(origfile);
s->rate = 44100;
s->format = ESD_STREAM | ESD_PLAY;
s->samples = 0;
s->data = NULL;
s->id = 0;
if (in_width == 8)
s->format |= ESD_BITS8;
else if (in_width == 16)
s->format |= ESD_BITS16;
bytes_per_frame = (in_width * in_channels) / 8;
if (in_channels == 1)
s->format |= ESD_MONO;
else if (in_channels == 2)
s->format |= ESD_STEREO;
s->rate = (int)in_rate;
s->samples = frame_count * bytes_per_frame;
s->data = (unsigned char *) malloc(frame_count * bytes_per_frame);
if ( !s->data )
{
(void) fprintf( stderr, "Error ! cannot allocate memory for sample !\n" );
(void) afCloseFile(in_file);
return NULL;
}
(void) afReadFrames(in_file, AF_DEFAULT_TRACK, s->data, frame_count);
(void) afCloseFile(in_file);
return s;
}
static
void
sound_esd_play(EsdSample_ptr s)
{
int size, confirm = 0;
#ifdef DEBUG
(void) fprintf( stderr, "sound_esd_play\n" );
#endif
if ((sound_fd < 0) || (!s))
return;
if (!s->id)
{
if (sound_fd >= 0)
{
if (s->data)
{
size = s->samples;
s->id = esd_sample_getid(sound_fd, s->file);
if (s->id < 0)
{
s->id = esd_sample_cache(sound_fd, s->format, s->rate, size, s->file);
write(sound_fd, s->data, size);
confirm = esd_confirm_sample_cache(sound_fd);
if (confirm != s->id)
s->id = 0;
}
free(s->data);
s->data = NULL;
}
}
}
if (s->id > 0)
esd_sample_play(sound_fd, s->id);
return;
}
static void
sound_esd_destroy_sample(EsdSample_ptr s)
{
#ifdef DEBUG
(void) fprintf( stderr, "sound_esd_destroy_sample\n" );
#endif
if ((s->id) && (sound_fd >= 0))
esd_sample_free(sound_fd, s->id);
if (s->data)
free(s->data);
if (s->file)
free(s->file);
}
static int
sound_esd_init(void)
{
int fd;
#ifdef DEBUG
(void) fprintf(stderr, "sound_esd_init\n");
#endif
if (sound_fd != -1)
return 0;
fd = esd_open_sound(NULL);
if (fd >= 0)
sound_fd = fd;
else
{
(void) fprintf(stderr, "Error initialising sound\n");
return -1;
}
return 0;
}
static void
sound_esd_shutdown(void)
{
#ifdef DEBUG
(void) fprintf( stderr, "sound_esd_shutdown\n" );
#endif
if (sound_fd >= 0)
{
EsdSample_ptr s = EsdSamplesList;
while ( s )
{
EsdSamplesList = s->next;
sound_esd_destroy_sample( s );
free( s );
s = EsdSamplesList;
}
close(sound_fd);
sound_fd = -1;
}
}
#endif
#ifdef USE_SOUND
void
playSound(char *filename, Bool verbose)
{
char* actual_sound;
actual_sound = getSound(filename);
if (verbose && strcmp(actual_sound, filename) != 0) {
(void) printf("Requested sound file : %s\n", filename);
(void) printf("Selected sound file : %s\n" , actual_sound);
}
if (actual_sound)
play_sound(actual_sound, verbose);
}
#endif