ref: bce6ff4b8b16c32cbfced092983823acf3c7deb1
dir: /libnpe_sdl2/mixer.c/
#include "_sdl.h"
#include <SDL2/SDL_mixer.h>
int audiofd = -1;
int musicpipe[2] = {-1, -1};
static int forkerpid = -1;
static int audiopid = -1;
void audioexec(void *);
void audioforker(void *);
void audioproc(void *);
static int musicvol = 128;
static int musicpaused = 0;
/* FIXME proper chains per channel */
Mix_EffectFunc_t effunc = nil;
int
Mix_OpenAudio(int freq, Uint16 format, int channels, int chunk)
{
USED(freq);
USED(format);
USED(channels);
USED(chunk);
return 0;
}
char*
Mix_GetError(void)
{
return "";
}
int
Mix_RegisterEffect(int chan, Mix_EffectFunc_t f, Mix_EffectDone_t d, void *arg)
{
USED(chan);
USED(f);
USED(d);
USED(arg);
effunc = f;
return 1;
}
Mix_Chunk*
Mix_QuickLoad_RAW(Uint8 *mem, Uint32 len)
{
USED(mem);
USED(len);
return nil;
}
int
Mix_PlayChannel(int chan, Mix_Chunk *chunk, int loops)
{
USED(chan);
USED(chunk);
USED(loops);
return -1;
}
int
Mix_HaltChannel(int channel)
{
USED(channel);
return 0;
}
void
Mix_FreeChunk(Mix_Chunk *c)
{
USED(c);
}
void
Mix_CloseAudio(void)
{
if(audiopid > 0)
postnote(PNPROC, audiopid, "quit");
audiopid = -1;
}
int
Mix_Init(int flags)
{
audiofd = open("/dev/audio", OWRITE);
if(audiofd < 0)
return -1;
audiopid = proccreate(audioproc, nil, 4096);
return flags;
}
int
Mix_VolumeMusic(int vol)
{
if(vol < 0)
vol = 0;
else if(vol > 128)
vol = 128;
musicvol = vol;
return 0;
}
int
Mix_PlayingMusic(void)
{
return forkerpid > 0 && !musicpaused;
}
int
Mix_PausedMusic(void)
{
return musicpaused;
}
void
Mix_ResumeMusic(void)
{
musicpaused = 0;
}
void
Mix_PauseMusic(void)
{
musicpaused = 1;
}
int
Mix_HaltMusic(void)
{
int x, y;
if(forkerpid < 0)
return 0;
postnote(PNGROUP, forkerpid, "halt");
x = musicpipe[0];
y = musicpipe[1];
musicpipe[0] = -1;
musicpipe[1] = -1;
close(x); close(y);
forkerpid = -1;
return 0;
}
int
Mix_PlayMusic(Mix_Music *music, int loops)
{
music->loops = loops;
pipe(musicpipe);
forkerpid = procrfork(audioforker, music, 4096, RFNOTEG);
return 0;
}
Mix_Music*
Mix_LoadMUS_RW(SDL_RWops *src, int freesrc)
{
Mix_Music *m;
char buf[1024];
int n;
m = calloc(1, sizeof(*m));
m->loc = smprint("/tmp/duke3d.mus.%d", getpid());
m->fd = create(m->loc, ORDWR|ORCLOSE, 0666);
while((n = SDL_RWread(src, buf, 1, sizeof buf)) > 0)
write(m->fd, buf, n);
if(freesrc)
SDL_RWclose(src);
return m;
}
void
audioexec(void *arg)
{
Mix_Music *m;
int i;
m = arg;
seek(m->fd, 0, 0);
dup(musicpipe[0], 1);
dup(m->fd, 0);
close(musicpipe[1]);
procexecl(nil, "/bin/games/midi", "midi", "-c", nil);
}
void
audioforker(void *arg)
{
Mix_Music *m;
Waitmsg *wm;
Channel *c;
m = arg;
c = threadwaitchan();
while(m->loops-- != 0){
procrfork(audioexec, m, 4096, RFFDG);
wm = recvp(c);
if(wm->msg != nil){
fprint(2, "err %s\n", wm->msg);
free(wm);
break;
}
free(wm);
}
}
void
audioproc(void *)
{
static uchar buf[1024];
static uchar sounds[1024];
s16int *mu;
s16int *so;
int i, n;
long v;
mu = (s16int*)buf;
so = (s16int*)sounds;
for(;;){
memset(buf, 0, sizeof buf);
if(musicpipe[1] > 0 && !musicpaused){
n = read(musicpipe[1], buf, sizeof buf);
if(n < 0)
continue;
for(i = 0; i < n/sizeof(*mu); i++)
mu[i] = ((long)mu[i] * musicvol)/128;
} else {
n = 0;
}
if(effunc != nil){
effunc(0, sounds, sizeof sounds, nil);
for(i = 0; i < sizeof sounds/sizeof(*so); i++){
v = mu[i] + so[i];
if(v > 0x7fff)
v = 0x7fff;
else if(v < -0x8000)
v = -0x8000;
mu[i] = v;
}
n = sizeof sounds;
}
write(audiofd, buf, n);
}
}