3 * AfterStep Sound System - sound module for Wharf
5 * Copyright (c) 1996 by Alfredo Kojima
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
32 #include <sys/types.h>
33 #include <sys/fcntl.h>
34 #include "libs/ftime.h"
37 #define AUDIO_DEVICE "/dev/audio"
39 typedef struct LList
{
46 typedef struct SoundEntry
{
51 /* timeout time for sound playing in seconds */
52 #define PLAY_TIMEOUT 1
54 /* table of audio data (not filenames) */
55 SoundEntry
**SoundTable
;
61 LList
*PlayQueue
=NULL
, *OldestQueued
=NULL
;
65 void *ckmalloc(size_t size
)
71 fprintf(stderr
,"%s: virtual memory exhausted.",ProgName
);
79 * makes a new sound entry
81 void Register(char *sound_file
, int code
)
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
,
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
);
103 SoundTable
[code
]->data
=ckmalloc(stat_buf
.st_size
);
104 file
=open(sound_file
, O_RDONLY
);
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
;
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
,
116 free(SoundTable
[code
]->data
);
117 free(SoundTable
[code
]);
119 SoundTable
[code
]=NULL
;
130 void PlaySound(int sid
)
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",
139 if (SoundPlayer
!=NULL
) {
140 static char cmd
[1024];
146 execlp(SoundPlayer
,SoundPlayer
,SoundTable
[sid
]->data
,NULL
);
148 while (wait(NULL
)<0);
151 sprintf(cmd,"%s %s",SoundPlayer,SoundTable[sid]->data);
157 audio
= open(AUDIO_DEVICE
,O_WRONLY
|O_NONBLOCK
);
158 if ((audio
<0) && errno
==EAGAIN
) {
160 audio
= open(AUDIO_DEVICE
,O_WRONLY
|O_NONBLOCK
);
163 write(audio
, SoundTable
[sid
]->data
,SoundTable
[sid
]->size
);
169 RETSIGTYPE
DoNothing(int foo
)
171 signal(SIGUSR1
, DoNothing
);
177 * play requested sound
178 * sound -1 is a quit command
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
;
190 signal(SIGUSR1, DoNothing);
192 read(InPipe
,&sound
,sizeof(sound
));
193 read(InPipe
,×tamp
,sizeof(timestamp
));
195 printf("exitting ASSound..\n");
198 if ((clock()-timestamp
)<PLAY_TIMEOUT
)
201 tmp
= ckmalloc(sizeof(LList
));
203 tmp
->timestamp
= clock();
204 tmp
->next
= PlayQueue
;
205 if (PlayQueue
==NULL
) {
209 PlayQueue
->prev
= tmp
;
212 signal(SIGUSR1
, HandleRequest
);
219 * argv[1] - pipe for reading data
220 * argv[2] - the name of the sound player to be used. ``-'' indicates
222 * argv[3]... - filenames of sound files with code n-3
224 int main(int argc
, char **argv
)
228 signal(SIGUSR1
, HandleRequest
);
231 fprintf(stderr
, "%s can only be started by an AfterStep module\n",
236 if (SoundPlayer
[0]=='-' && SoundPlayer
[1]==0) {
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);
245 InPipe
= atoi(argv
[1]);
249 while (OldestQueued
!=NULL
) {
250 if ((clock()-OldestQueued
->timestamp
) < PLAY_TIMEOUT
)
251 PlaySound(OldestQueued
->data
);
252 tmp
= OldestQueued
->prev
;