version 1.38, 2010/01/05 10:18:12 |
version 1.39, 2010/01/10 21:47:41 |
|
|
#include "miofile.h" |
#include "miofile.h" |
#include "safile.h" |
#include "safile.h" |
#include "midi.h" |
#include "midi.h" |
|
#ifdef DEBUG |
|
#include "dbg.h" |
|
#endif |
|
|
unsigned dev_bufsz, dev_round, dev_rate; |
unsigned dev_bufsz, dev_round, dev_rate; |
struct aparams dev_ipar, dev_opar; |
struct aparams dev_ipar, dev_opar; |
|
|
if (f == NULL) |
if (f == NULL) |
return 0; |
return 0; |
if (dipar) { |
if (dipar) { |
|
#ifdef DEBUG |
|
if (debug_level >= 2) { |
|
dbg_puts("hw recording "); |
|
aparams_dbg(dipar); |
|
dbg_puts("\n"); |
|
} |
|
#endif |
dev_rate = dipar->rate; |
dev_rate = dipar->rate; |
} |
} |
if (dopar) { |
if (dopar) { |
|
#ifdef DEBUG |
|
if (debug_level >= 2) { |
|
dbg_puts("hw playing "); |
|
aparams_dbg(dopar); |
|
dbg_puts("\n"); |
|
} |
|
#endif |
dev_rate = dopar->rate; |
dev_rate = dopar->rate; |
} |
} |
ibufsz = obufsz = dev_bufsz; |
ibufsz = obufsz = dev_bufsz; |
|
|
dev_mix = NULL; |
dev_mix = NULL; |
} |
} |
dev_bufsz = (dopar) ? obufsz : ibufsz; |
dev_bufsz = (dopar) ? obufsz : ibufsz; |
|
#ifdef DEBUG |
|
if (debug_level >= 2) { |
|
dbg_puts("device block size is "); |
|
dbg_putu(dev_round); |
|
dbg_puts(" frames, using "); |
|
dbg_putu(dev_bufsz / dev_round); |
|
dbg_puts(" blocks\n"); |
|
} |
|
#endif |
dev_start(); |
dev_start(); |
return 1; |
return 1; |
} |
} |
|
|
{ |
{ |
struct file *f; |
struct file *f; |
|
|
|
#ifdef DEBUG |
|
if (debug_level >= 2) |
|
dbg_puts("closing audio device\n"); |
|
#endif |
if (dev_mix) { |
if (dev_mix) { |
/* |
/* |
* Put the mixer in ``autoquit'' state and generate |
* Put the mixer in ``autoquit'' state and generate |
|
|
ibuf = *sibuf; |
ibuf = *sibuf; |
for (;;) { |
for (;;) { |
if (!ibuf || !ibuf->rproc) { |
if (!ibuf || !ibuf->rproc) { |
|
#ifdef DEBUG |
|
if (debug_level >= 3) { |
|
abuf_dbg(*sibuf); |
|
dbg_puts(": not connected to device\n"); |
|
} |
|
#endif |
return 0; |
return 0; |
} |
} |
if (ibuf->rproc == dev_mix) |
if (ibuf->rproc == dev_mix) |
|
|
obuf = *sobuf; |
obuf = *sobuf; |
for (;;) { |
for (;;) { |
if (!obuf || !obuf->wproc) { |
if (!obuf || !obuf->wproc) { |
|
#ifdef DEBUG |
|
if (debug_level >= 3) { |
|
abuf_dbg(*sobuf); |
|
dbg_puts(": not connected to device\n"); |
|
} |
|
#endif |
return 0; |
return 0; |
} |
} |
if (obuf->wproc == dev_sub) |
if (obuf->wproc == dev_sub) |
|
|
rbuf->bpf * (pbuf->abspos + pbuf->used) - |
rbuf->bpf * (pbuf->abspos + pbuf->used) - |
pbuf->bpf * rbuf->abspos; |
pbuf->bpf * rbuf->abspos; |
delta /= pbuf->bpf * rbuf->bpf; |
delta /= pbuf->bpf * rbuf->bpf; |
|
#ifdef DEBUG |
|
if (debug_level >= 3) { |
|
dbg_puts("syncing device, delta = "); |
|
dbg_putu(delta); |
|
dbg_puts(": "); |
|
abuf_dbg(pbuf); |
|
dbg_puts(" abspos = "); |
|
dbg_putu(pbuf->abspos); |
|
dbg_puts(" used = "); |
|
dbg_putu(pbuf->used); |
|
dbg_puts(" <---> "); |
|
abuf_dbg(rbuf); |
|
dbg_puts(" abspos = "); |
|
dbg_putu(rbuf->abspos); |
|
dbg_puts("\n"); |
|
} |
|
#endif |
if (delta > 0) { |
if (delta > 0) { |
/* |
/* |
* The play chain is ahead (most cases) drop some of |
* The play chain is ahead (most cases) drop some of |
|
|
rlat -= delta; |
rlat -= delta; |
else if (delta < 0) |
else if (delta < 0) |
plat += delta; |
plat += delta; |
|
#ifdef DEBUG |
|
if (rlat != plat) { |
|
dbg_puts("dev_getpos: play/rec out of sync: plat = "); |
|
dbg_puti(plat); |
|
dbg_puts(", rlat = "); |
|
dbg_puti(rlat); |
|
dbg_puts("\n"); |
|
} |
|
#endif |
} |
} |
return dev_mix ? plat : rlat; |
return dev_mix ? plat : rlat; |
} |
} |
|
|
void |
void |
dev_setvol(struct abuf *ibuf, int vol) |
dev_setvol(struct abuf *ibuf, int vol) |
{ |
{ |
|
#ifdef DEBUG |
|
if (debug_level >= 3) { |
|
abuf_dbg(ibuf); |
|
dbg_puts(": setting volume to "); |
|
dbg_putu(vol); |
|
dbg_puts("\n"); |
|
} |
|
#endif |
if (!dev_getep(&ibuf, NULL)) { |
if (!dev_getep(&ibuf, NULL)) { |
return; |
return; |
} |
} |
|
|
struct abuf *buf; |
struct abuf *buf; |
|
|
if (dev_mix) { |
if (dev_mix) { |
|
#ifdef DEBUG |
|
if (!LIST_EMPTY(&dev_mix->ibuflist)) { |
|
dbg_puts("play end not idle, can't clear device\n"); |
|
dbg_panic(); |
|
} |
|
#endif |
buf = LIST_FIRST(&dev_mix->obuflist); |
buf = LIST_FIRST(&dev_mix->obuflist); |
while (buf) { |
while (buf) { |
abuf_clear(buf); |
abuf_clear(buf); |
|
|
mix_clear(dev_mix); |
mix_clear(dev_mix); |
} |
} |
if (dev_sub) { |
if (dev_sub) { |
|
#ifdef DEBUG |
|
if (!LIST_EMPTY(&dev_sub->obuflist)) { |
|
dbg_puts("record end not idle, can't clear device\n"); |
|
dbg_panic(); |
|
} |
|
#endif |
buf = LIST_FIRST(&dev_sub->ibuflist); |
buf = LIST_FIRST(&dev_sub->ibuflist); |
while (buf) { |
while (buf) { |
abuf_clear(buf); |
abuf_clear(buf); |