cvsimport
[fvwm.git] / modules / FvwmWharf / ASSound / ASSound.c
blobfc0b849dc03ad153d922db82fadc0300ea2e7c49
1 /* -*-c-*- */
2 /*
3 * AfterStep Sound System - sound module for Wharf
5 * Copyright (c) 1996 by Alfredo Kojima
6 */
7 /*
8 * Todo:
9 * realtime audio mixing
10 * replace the Audio module
13 /* This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include "config.h"
30 #include <stdio.h>
31 #include <sys/stat.h>
32 #include <sys/types.h>
33 #include <sys/fcntl.h>
34 #include "libs/ftime.h"
35 #include <signal.h>
36 #include <unistd.h>
37 #define AUDIO_DEVICE "/dev/audio"
39 typedef struct LList {
40 struct LList *next;
41 struct LList *prev;
42 int data;
43 int timestamp;
44 } LList;
46 typedef struct SoundEntry {
47 char *data;
48 int size;
49 } SoundEntry;
51 /* timeout time for sound playing in seconds */
52 #define PLAY_TIMEOUT 1
54 /* table of audio data (not filenames) */
55 SoundEntry **SoundTable;
57 int LastSound=0;
58 char *SoundPlayer;
60 char *ProgName;
61 LList *PlayQueue=NULL, *OldestQueued=NULL;
63 int InPipe;
65 void *ckmalloc(size_t size)
67 void *tmp;
69 tmp=malloc(size);
70 if (tmp==NULL) {
71 fprintf(stderr,"%s: virtual memory exhausted.",ProgName);
72 exit(1);
74 return tmp;
78 * Register --
79 * makes a new sound entry
81 void Register(char *sound_file, int code)
83 int file;
84 struct stat stat_buf;
86 if (sound_file[0]=='.' && sound_file[1]==0) {
87 SoundTable[code]=ckmalloc(sizeof(SoundEntry));
88 SoundTable[code]->size = -1;
89 return; /* dummy sound */
91 if (stat(sound_file, &stat_buf)<0) {
92 fprintf(stderr,"%s: sound file %s not found\n",ProgName,
93 sound_file);
94 return;
96 SoundTable[code]=ckmalloc(sizeof(SoundEntry));
97 if (SoundPlayer!=NULL) {
98 SoundTable[code]->data=ckmalloc(strlen(sound_file));
99 SoundTable[code]->size=1;
100 strcpy(SoundTable[code]->data,sound_file);
101 return;
103 SoundTable[code]->data=ckmalloc(stat_buf.st_size);
104 file=open(sound_file, O_RDONLY);
105 if (file<0) {
106 fprintf(stderr,"%s: can't open sound file %s\n",ProgName, sound_file);
107 free(SoundTable[code]->data);
108 free(SoundTable[code]);
109 SoundTable[code]=NULL;
110 return;
112 SoundTable[code]->size=read(file,SoundTable[code]->data,stat_buf.st_size);
113 if (SoundTable[code]->size<1) {
114 fprintf(stderr,"%s: error reading sound file %s\n",ProgName,
115 sound_file);
116 free(SoundTable[code]->data);
117 free(SoundTable[code]);
118 close(file);
119 SoundTable[code]=NULL;
120 return;
122 close(file);
126 * PlaySound --
127 * plays a sound
130 void PlaySound(int sid)
132 int audio=-1;
133 if ((sid < LastSound) && (SoundTable[sid]->size<=0)) return;
134 if ((sid>=LastSound) || (sid<0) || SoundTable[sid]==NULL) {
135 fprintf(stderr,"%s: request to play invalid sound received\n",
136 ProgName);
137 return;
139 if (SoundPlayer!=NULL) {
140 static char cmd[1024];
141 pid_t child;
143 child = fork();
144 if (child<0) return;
145 else if (child==0) {
146 execlp(SoundPlayer,SoundPlayer,SoundTable[sid]->data,NULL);
147 } else {
148 while (wait(NULL)<0);
151 sprintf(cmd,"%s %s",SoundPlayer,SoundTable[sid]->data);
152 system(cmd);
154 return;
156 #if 0
157 audio = open(AUDIO_DEVICE,O_WRONLY|O_NONBLOCK);
158 if ((audio<0) && errno==EAGAIN) {
159 sleep(1);
160 audio = open(AUDIO_DEVICE,O_WRONLY|O_NONBLOCK);
161 if (audio<0) return;
163 write(audio, SoundTable[sid]->data,SoundTable[sid]->size);
164 close(audio);
165 audio=-1;
166 #endif
169 RETSIGTYPE DoNothing(int foo)
171 signal(SIGUSR1, DoNothing);
172 SIGNAL_RETURN;
176 * HandleRequest --
177 * play requested sound
178 * sound -1 is a quit command
180 * Note:
181 * Something not good will happed if a new play request
182 * arrives before exiting the handler
184 void HandleRequest(int foo)
186 int sound, timestamp;
187 char *buffer;
188 LList *tmp;
190 signal(SIGUSR1, DoNothing);
192 read(InPipe,&sound,sizeof(sound));
193 read(InPipe,&timestamp,sizeof(timestamp));
194 if (sound<0) {
195 printf("exitting ASSound..\n");
196 exit(0);
198 if ((clock()-timestamp)<PLAY_TIMEOUT)
199 PlaySound(sound);
200 #if 0
201 tmp = ckmalloc(sizeof(LList));
202 tmp->data = sound;
203 tmp->timestamp = clock();
204 tmp->next = PlayQueue;
205 if (PlayQueue==NULL) {
206 OldestQueued = tmp;
207 tmp->prev = NULL;
208 } else {
209 PlayQueue->prev = tmp;
211 PlayQueue = tmp;
212 signal(SIGUSR1, HandleRequest);
213 #endif
217 * Program startup.
218 * Arguments:
219 * argv[1] - pipe for reading data
220 * argv[2] - the name of the sound player to be used. ``-'' indicates
221 * internal player.
222 * argv[3]... - filenames of sound files with code n-3
224 int main(int argc, char **argv)
226 int i;
228 signal(SIGUSR1, HandleRequest);
229 ProgName=argv[0];
230 if (argc<4) {
231 fprintf(stderr, "%s can only be started by an AfterStep module\n",
232 ProgName);
233 exit(1);
235 SoundPlayer=argv[2];
236 if (SoundPlayer[0]=='-' && SoundPlayer[1]==0) {
237 SoundPlayer=NULL;
238 printf("%s:need a sound player.\n",ProgName);
240 SoundTable=ckmalloc(sizeof(SoundEntry *)*(argc-3));
241 for(i=3; i<argc; i++) {
242 Register(argv[i], i-3);
244 LastSound=i-3;
245 InPipe = atoi(argv[1]);
246 while(1) {
247 #if 0
248 LList *tmp;
249 while (OldestQueued!=NULL) {
250 if ((clock()-OldestQueued->timestamp) < PLAY_TIMEOUT)
251 PlaySound(OldestQueued->data);
252 tmp = OldestQueued->prev;
253 free(OldestQueued);
254 OldestQueued=tmp;
256 pause();
257 #endif
258 HandleRequest(0);