/* -*-c-*- */ /* * AfterStep Sound System - sound module for Wharf * * Copyright (c) 1996 by Alfredo Kojima */ /* * Todo: * realtime audio mixing * replace the Audio module */ /* 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; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "config.h" #include #include #include #include #include "libs/ftime.h" #include #include #define AUDIO_DEVICE "/dev/audio" typedef struct LList { struct LList *next; struct LList *prev; int data; int timestamp; } LList; typedef struct SoundEntry { char *data; int size; } SoundEntry; /* timeout time for sound playing in seconds */ #define PLAY_TIMEOUT 1 /* table of audio data (not filenames) */ SoundEntry **SoundTable; int LastSound=0; char *SoundPlayer; char *ProgName; LList *PlayQueue=NULL, *OldestQueued=NULL; int InPipe; void *ckmalloc(size_t size) { void *tmp; tmp=malloc(size); if (tmp==NULL) { fprintf(stderr,"%s: virtual memory exhausted.",ProgName); exit(1); } return tmp; } /* * Register -- * makes a new sound entry */ void Register(char *sound_file, int code) { int file; struct stat stat_buf; if (sound_file[0]=='.' && sound_file[1]==0) { SoundTable[code]=ckmalloc(sizeof(SoundEntry)); SoundTable[code]->size = -1; return; /* dummy sound */ } if (stat(sound_file, &stat_buf)<0) { fprintf(stderr,"%s: sound file %s not found\n",ProgName, sound_file); return; } SoundTable[code]=ckmalloc(sizeof(SoundEntry)); if (SoundPlayer!=NULL) { SoundTable[code]->data=ckmalloc(strlen(sound_file)); SoundTable[code]->size=1; strcpy(SoundTable[code]->data,sound_file); return; } SoundTable[code]->data=ckmalloc(stat_buf.st_size); file=open(sound_file, O_RDONLY); if (file<0) { fprintf(stderr,"%s: can't open sound file %s\n",ProgName, sound_file); free(SoundTable[code]->data); free(SoundTable[code]); SoundTable[code]=NULL; return; } SoundTable[code]->size=read(file,SoundTable[code]->data,stat_buf.st_size); if (SoundTable[code]->size<1) { fprintf(stderr,"%s: error reading sound file %s\n",ProgName, sound_file); free(SoundTable[code]->data); free(SoundTable[code]); close(file); SoundTable[code]=NULL; return; } close(file); } /* * PlaySound -- * plays a sound */ void PlaySound(int sid) { int audio=-1; if ((sid < LastSound) && (SoundTable[sid]->size<=0)) return; if ((sid>=LastSound) || (sid<0) || SoundTable[sid]==NULL) { fprintf(stderr,"%s: request to play invalid sound received\n", ProgName); return; } if (SoundPlayer!=NULL) { static char cmd[1024]; pid_t child; child = fork(); if (child<0) return; else if (child==0) { execlp(SoundPlayer,SoundPlayer,SoundTable[sid]->data,NULL); } else { while (wait(NULL)<0); } /* sprintf(cmd,"%s %s",SoundPlayer,SoundTable[sid]->data); system(cmd); */ return; } #if 0 audio = open(AUDIO_DEVICE,O_WRONLY|O_NONBLOCK); if ((audio<0) && errno==EAGAIN) { sleep(1); audio = open(AUDIO_DEVICE,O_WRONLY|O_NONBLOCK); if (audio<0) return; } write(audio, SoundTable[sid]->data,SoundTable[sid]->size); close(audio); audio=-1; #endif } RETSIGTYPE DoNothing(int foo) { signal(SIGUSR1, DoNothing); SIGNAL_RETURN; } /* * HandleRequest -- * play requested sound * sound -1 is a quit command * * Note: * Something not good will happed if a new play request * arrives before exiting the handler */ void HandleRequest(int foo) { int sound, timestamp; char *buffer; LList *tmp; /* signal(SIGUSR1, DoNothing); */ read(InPipe,&sound,sizeof(sound)); read(InPipe,×tamp,sizeof(timestamp)); if (sound<0) { printf("exitting ASSound..\n"); exit(0); } if ((clock()-timestamp)data = sound; tmp->timestamp = clock(); tmp->next = PlayQueue; if (PlayQueue==NULL) { OldestQueued = tmp; tmp->prev = NULL; } else { PlayQueue->prev = tmp; } PlayQueue = tmp; signal(SIGUSR1, HandleRequest); #endif } /* * Program startup. * Arguments: * argv[1] - pipe for reading data * argv[2] - the name of the sound player to be used. ``-'' indicates * internal player. * argv[3]... - filenames of sound files with code n-3 */ int main(int argc, char **argv) { int i; signal(SIGUSR1, HandleRequest); ProgName=argv[0]; if (argc<4) { fprintf(stderr, "%s can only be started by an AfterStep module\n", ProgName); exit(1); } SoundPlayer=argv[2]; if (SoundPlayer[0]=='-' && SoundPlayer[1]==0) { SoundPlayer=NULL; printf("%s:need a sound player.\n",ProgName); } SoundTable=ckmalloc(sizeof(SoundEntry *)*(argc-3)); for(i=3; itimestamp) < PLAY_TIMEOUT) PlaySound(OldestQueued->data); tmp = OldestQueued->prev; free(OldestQueued); OldestQueued=tmp; } pause(); #endif HandleRequest(0); } }