#include "dat.h" #include "fns.h" #include "error.h" #include "audio.h" #include #include enum { Audio_Mic_Val, Audio_Linein_Val, Audio_Speaker_Val, Audio_Headphone_Val, Audio_Lineout_Val, Audio_Pcm_Val, Audio_Ulaw_Val, Audio_Alaw_Val, }; #include "audio-tbls.c" static pa_simple *pa; static Audio_t av; static QLock palock; static int choosefmt(Audio_d *i) { switch(i->bits) { case 8: switch(i->enc) { case Audio_Alaw_Val: return PA_SAMPLE_ALAW; case Audio_Ulaw_Val: return PA_SAMPLE_ULAW; case Audio_Pcm_Val: return PA_SAMPLE_U8; } break; case 16: if(i->enc == Audio_Pcm_Val) return PA_SAMPLE_S16LE; break; } return -1; } static int mkspec(pa_sample_spec *spec, Audio_t *info) { spec->channels = info->out.chan; spec->rate = info->out.rate; if((spec->format = choosefmt(&info->out)) < 0) return -1; return 0; } Audio_t* getaudiodev(void) { return &av; } void audio_file_init(void) { audio_info_init(&av); } void audio_file_open(Chan *c, int omode) { int err; pa_sample_spec spec; USED(c); if(omode == OREAD || omode == ORDWR) error("reading isn't implemented"); qlock(&palock); if(waserror()) { qunlock(&palock); nexterror(); } if(mkspec(&spec, &av) < 0) error(Ebadarg); if(pa == NULL) pa = pa_simple_new(NULL, "emu", PA_STREAM_PLAYBACK, NULL, "emu", &spec, NULL, NULL, &err); if(pa == NULL) error(pa_strerror(err)); qunlock(&palock); poperror(); } void audio_file_close(Chan *c) { USED(c); qlock(&palock); pa_simple_drain(pa, NULL); qunlock(&palock); } long audio_file_read(Chan *c, void *va, long count, vlong offset) { USED(c); USED(va); USED(count); USED(offset); error("not implemented"); return -1; } long audio_file_write(Chan *c, void *va, long count, vlong offset) { int err; USED(c); USED(offset); qlock(&palock); if(waserror()) { qunlock(&palock); nexterror(); } if(pa_simple_write(pa, va, count, &err) < 0) error(pa_strerror(err)); qunlock(&palock); poperror(); return count; } long audio_ctl_write(Chan *c, void *va, long count, vlong offset) { pa_sample_spec spec; int err; USED(c); USED(offset); if(!canqlock(&palock)) error("device busy"); if(waserror()) { qunlock(&palock); nexterror(); } if(!audioparse(va, count, &av) || mkspec(&spec, &av) < 0) error(Ebadarg); if(pa != NULL) pa_simple_free(pa); pa = pa_simple_new(NULL, "emu", PA_STREAM_PLAYBACK, NULL, "emu", &spec, NULL, NULL, &err); if(pa == NULL) error(pa_strerror(err)); qunlock(&palock); poperror(); return count; }