#include <kernel/kernel.h> #include <kernel/driver.h> #include <kernel/sys.h> #include <errno.h> #include "sound.h" sound_t *sb_init(device_t *dev); sound_t *wss_init(device_t *dev); sound_t *solo_init(device_t *dev); typedef struct sound_dev_t sound_dev_t; struct sound_dev_t { device_t dev; sound_t *snd; dword play_end; unsigned rate, bits_per_sample, channels; }; bool sndRequest(device_t* dev, request_t* req) { sound_dev_t *snd = (sound_dev_t*) dev; byte *buf; dword end; switch (req->code) { case DEV_ISR: if (req->params.isr.irq == 0) { if (snd->play_end && sysUpTime() >= snd->play_end) { snd->play_end = 0; snd->snd->stop_playback(snd->snd, false); TRACE0("sndRequest: stop playback\n"); } } else snd->snd->irq(snd->snd, req->params.isr.irq); return true; case DEV_REMOVE: devRegisterIrq(&snd->dev, 0, false); snd->snd->close(snd->snd); hndFree(snd); case DEV_OPEN: case DEV_CLOSE: hndSignal(req->event, true); return true; case DEV_WRITE: end = sysUpTime() + (req->params.write.length * 1000 * 8) / (snd->rate * snd->bits_per_sample); req->user_length = req->params.write.length; req->params.write.length = 0; buf = (byte*) req->params.write.buffer; while (req->params.write.length < req->user_length) { snd->snd->write_sample(snd->snd, buf[req->params.write.length], buf[req->params.write.length]); req->params.write.length++; } //snd->play_end = end; hndSignal(req->event, true); return true; } req->result = ENOTIMPL; return false; } device_t* sndAddDevice(driver_t* drv, const wchar_t* name, device_config_t* cfg) { sound_dev_t* snd; request_t req; snd = hndAlloc(sizeof(sound_dev_t), NULL); snd->dev.request = sndRequest; snd->dev.driver = drv; snd->dev.config = cfg; snd->snd = solo_init(&snd->dev); if (snd->snd == NULL) { hndFree(snd); return NULL; } if (!snd->snd->open(snd->snd)) { snd->snd->close(snd->snd); hndFree(snd); return NULL; } snd->play_end = 0; snd->rate = 22050; snd->bits_per_sample = 8; snd->channels = 1; snd->rate = snd->snd->find_closest_rate(snd->snd, snd->rate); if (snd->rate == 0) { snd->snd->close(snd->snd); hndFree(snd); return NULL; } snd->snd->set_fmt(snd->snd, snd->bits_per_sample, snd->channels, snd->rate); devRegisterIrq(&snd->dev, 0, true); req.code = DEV_WRITE; req.params.write.buffer = (void*) 0x1000; req.params.write.length = 0x10000; devRequestSync(&snd->dev, &req); return &snd->dev; } bool STDCALL INIT_CODE drvInit(driver_t* drv) { drv->add_device = sndAddDevice; return true; }