diff options
Diffstat (limited to 'audio/winwaveaudio.c')
-rw-r--r-- | audio/winwaveaudio.c | 717 |
1 files changed, 0 insertions, 717 deletions
diff --git a/audio/winwaveaudio.c b/audio/winwaveaudio.c deleted file mode 100644 index 8dbd145ca1..0000000000 --- a/audio/winwaveaudio.c +++ /dev/null @@ -1,717 +0,0 @@ -/* public domain */ - -#include "qemu-common.h" -#include "sysemu/sysemu.h" -#include "audio.h" - -#define AUDIO_CAP "winwave" -#include "audio_int.h" - -#include <windows.h> -#include <mmsystem.h> - -#include "audio_win_int.h" - -static struct { - int dac_headers; - int dac_samples; - int adc_headers; - int adc_samples; -} conf = { - .dac_headers = 4, - .dac_samples = 1024, - .adc_headers = 4, - .adc_samples = 1024 -}; - -typedef struct { - HWVoiceOut hw; - HWAVEOUT hwo; - WAVEHDR *hdrs; - HANDLE event; - void *pcm_buf; - int avail; - int pending; - int curhdr; - int paused; - CRITICAL_SECTION crit_sect; -} WaveVoiceOut; - -typedef struct { - HWVoiceIn hw; - HWAVEIN hwi; - WAVEHDR *hdrs; - HANDLE event; - void *pcm_buf; - int curhdr; - int paused; - int rpos; - int avail; - CRITICAL_SECTION crit_sect; -} WaveVoiceIn; - -static void winwave_log_mmresult (MMRESULT mr) -{ - const char *str = "BUG"; - - switch (mr) { - case MMSYSERR_NOERROR: - str = "Success"; - break; - - case MMSYSERR_INVALHANDLE: - str = "Specified device handle is invalid"; - break; - - case MMSYSERR_BADDEVICEID: - str = "Specified device id is out of range"; - break; - - case MMSYSERR_NODRIVER: - str = "No device driver is present"; - break; - - case MMSYSERR_NOMEM: - str = "Unable to allocate or lock memory"; - break; - - case WAVERR_SYNC: - str = "Device is synchronous but waveOutOpen was called " - "without using the WINWAVE_ALLOWSYNC flag"; - break; - - case WAVERR_UNPREPARED: - str = "The data block pointed to by the pwh parameter " - "hasn't been prepared"; - break; - - case WAVERR_STILLPLAYING: - str = "There are still buffers in the queue"; - break; - - default: - dolog ("Reason: Unknown (MMRESULT %#x)\n", mr); - return; - } - - dolog ("Reason: %s\n", str); -} - -static void GCC_FMT_ATTR (2, 3) winwave_logerr ( - MMRESULT mr, - const char *fmt, - ... - ) -{ - va_list ap; - - va_start (ap, fmt); - AUD_vlog (AUDIO_CAP, fmt, ap); - va_end (ap); - - AUD_log (NULL, " failed\n"); - winwave_log_mmresult (mr); -} - -static void winwave_anal_close_out (WaveVoiceOut *wave) -{ - MMRESULT mr; - - mr = waveOutClose (wave->hwo); - if (mr != MMSYSERR_NOERROR) { - winwave_logerr (mr, "waveOutClose"); - } - wave->hwo = NULL; -} - -static void CALLBACK winwave_callback_out ( - HWAVEOUT hwo, - UINT msg, - DWORD_PTR dwInstance, - DWORD_PTR dwParam1, - DWORD_PTR dwParam2 - ) -{ - WaveVoiceOut *wave = (WaveVoiceOut *) dwInstance; - - switch (msg) { - case WOM_DONE: - { - WAVEHDR *h = (WAVEHDR *) dwParam1; - if (!h->dwUser) { - h->dwUser = 1; - EnterCriticalSection (&wave->crit_sect); - { - wave->avail += conf.dac_samples; - } - LeaveCriticalSection (&wave->crit_sect); - if (wave->hw.poll_mode) { - if (!SetEvent (wave->event)) { - dolog ("DAC SetEvent failed %lx\n", GetLastError ()); - } - } - } - } - break; - - case WOM_CLOSE: - case WOM_OPEN: - break; - - default: - dolog ("unknown wave out callback msg %x\n", msg); - } -} - -static int winwave_init_out (HWVoiceOut *hw, struct audsettings *as) -{ - int i; - int err; - MMRESULT mr; - WAVEFORMATEX wfx; - WaveVoiceOut *wave; - - wave = (WaveVoiceOut *) hw; - - InitializeCriticalSection (&wave->crit_sect); - - err = waveformat_from_audio_settings (&wfx, as); - if (err) { - goto err0; - } - - mr = waveOutOpen (&wave->hwo, WAVE_MAPPER, &wfx, - (DWORD_PTR) winwave_callback_out, - (DWORD_PTR) wave, CALLBACK_FUNCTION); - if (mr != MMSYSERR_NOERROR) { - winwave_logerr (mr, "waveOutOpen"); - goto err1; - } - - wave->hdrs = audio_calloc (AUDIO_FUNC, conf.dac_headers, - sizeof (*wave->hdrs)); - if (!wave->hdrs) { - goto err2; - } - - audio_pcm_init_info (&hw->info, as); - hw->samples = conf.dac_samples * conf.dac_headers; - wave->avail = hw->samples; - - wave->pcm_buf = audio_calloc (AUDIO_FUNC, conf.dac_samples, - conf.dac_headers << hw->info.shift); - if (!wave->pcm_buf) { - goto err3; - } - - for (i = 0; i < conf.dac_headers; ++i) { - WAVEHDR *h = &wave->hdrs[i]; - - h->dwUser = 0; - h->dwBufferLength = conf.dac_samples << hw->info.shift; - h->lpData = advance (wave->pcm_buf, i * h->dwBufferLength); - h->dwFlags = 0; - - mr = waveOutPrepareHeader (wave->hwo, h, sizeof (*h)); - if (mr != MMSYSERR_NOERROR) { - winwave_logerr (mr, "waveOutPrepareHeader(%d)", i); - goto err4; - } - } - - return 0; - - err4: - g_free (wave->pcm_buf); - err3: - g_free (wave->hdrs); - err2: - winwave_anal_close_out (wave); - err1: - err0: - return -1; -} - -static int winwave_write (SWVoiceOut *sw, void *buf, int len) -{ - return audio_pcm_sw_write (sw, buf, len); -} - -static int winwave_run_out (HWVoiceOut *hw, int live) -{ - WaveVoiceOut *wave = (WaveVoiceOut *) hw; - int decr; - int doreset; - - EnterCriticalSection (&wave->crit_sect); - { - decr = audio_MIN (live, wave->avail); - decr = audio_pcm_hw_clip_out (hw, wave->pcm_buf, decr, wave->pending); - wave->pending += decr; - wave->avail -= decr; - } - LeaveCriticalSection (&wave->crit_sect); - - doreset = hw->poll_mode && (wave->pending >= conf.dac_samples); - if (doreset && !ResetEvent (wave->event)) { - dolog ("DAC ResetEvent failed %lx\n", GetLastError ()); - } - - while (wave->pending >= conf.dac_samples) { - MMRESULT mr; - WAVEHDR *h = &wave->hdrs[wave->curhdr]; - - h->dwUser = 0; - mr = waveOutWrite (wave->hwo, h, sizeof (*h)); - if (mr != MMSYSERR_NOERROR) { - winwave_logerr (mr, "waveOutWrite(%d)", wave->curhdr); - break; - } - - wave->pending -= conf.dac_samples; - wave->curhdr = (wave->curhdr + 1) % conf.dac_headers; - } - - return decr; -} - -static void winwave_poll (void *opaque) -{ - (void) opaque; - audio_run ("winwave_poll"); -} - -static void winwave_fini_out (HWVoiceOut *hw) -{ - int i; - MMRESULT mr; - WaveVoiceOut *wave = (WaveVoiceOut *) hw; - - mr = waveOutReset (wave->hwo); - if (mr != MMSYSERR_NOERROR) { - winwave_logerr (mr, "waveOutReset"); - } - - for (i = 0; i < conf.dac_headers; ++i) { - mr = waveOutUnprepareHeader (wave->hwo, &wave->hdrs[i], - sizeof (wave->hdrs[i])); - if (mr != MMSYSERR_NOERROR) { - winwave_logerr (mr, "waveOutUnprepareHeader(%d)", i); - } - } - - winwave_anal_close_out (wave); - - if (wave->event) { - qemu_del_wait_object (wave->event, winwave_poll, wave); - if (!CloseHandle (wave->event)) { - dolog ("DAC CloseHandle failed %lx\n", GetLastError ()); - } - wave->event = NULL; - } - - g_free (wave->pcm_buf); - wave->pcm_buf = NULL; - - g_free (wave->hdrs); - wave->hdrs = NULL; -} - -static int winwave_ctl_out (HWVoiceOut *hw, int cmd, ...) -{ - MMRESULT mr; - WaveVoiceOut *wave = (WaveVoiceOut *) hw; - - switch (cmd) { - case VOICE_ENABLE: - { - va_list ap; - int poll_mode; - - va_start (ap, cmd); - poll_mode = va_arg (ap, int); - va_end (ap); - - if (poll_mode && !wave->event) { - wave->event = CreateEvent (NULL, TRUE, TRUE, NULL); - if (!wave->event) { - dolog ("DAC CreateEvent: %lx, poll mode will be disabled\n", - GetLastError ()); - } - } - - if (wave->event) { - int ret; - - ret = qemu_add_wait_object (wave->event, winwave_poll, wave); - hw->poll_mode = (ret == 0); - } - else { - hw->poll_mode = 0; - } - wave->paused = 0; - } - return 0; - - case VOICE_DISABLE: - if (!wave->paused) { - mr = waveOutReset (wave->hwo); - if (mr != MMSYSERR_NOERROR) { - winwave_logerr (mr, "waveOutReset"); - } - else { - wave->paused = 1; - } - } - if (wave->event) { - qemu_del_wait_object (wave->event, winwave_poll, wave); - } - return 0; - } - return -1; -} - -static void winwave_anal_close_in (WaveVoiceIn *wave) -{ - MMRESULT mr; - - mr = waveInClose (wave->hwi); - if (mr != MMSYSERR_NOERROR) { - winwave_logerr (mr, "waveInClose"); - } - wave->hwi = NULL; -} - -static void CALLBACK winwave_callback_in ( - HWAVEIN *hwi, - UINT msg, - DWORD_PTR dwInstance, - DWORD_PTR dwParam1, - DWORD_PTR dwParam2 - ) -{ - WaveVoiceIn *wave = (WaveVoiceIn *) dwInstance; - - switch (msg) { - case WIM_DATA: - { - WAVEHDR *h = (WAVEHDR *) dwParam1; - if (!h->dwUser) { - h->dwUser = 1; - EnterCriticalSection (&wave->crit_sect); - { - wave->avail += conf.adc_samples; - } - LeaveCriticalSection (&wave->crit_sect); - if (wave->hw.poll_mode) { - if (!SetEvent (wave->event)) { - dolog ("ADC SetEvent failed %lx\n", GetLastError ()); - } - } - } - } - break; - - case WIM_CLOSE: - case WIM_OPEN: - break; - - default: - dolog ("unknown wave in callback msg %x\n", msg); - } -} - -static void winwave_add_buffers (WaveVoiceIn *wave, int samples) -{ - int doreset; - - doreset = wave->hw.poll_mode && (samples >= conf.adc_samples); - if (doreset && !ResetEvent (wave->event)) { - dolog ("ADC ResetEvent failed %lx\n", GetLastError ()); - } - - while (samples >= conf.adc_samples) { - MMRESULT mr; - WAVEHDR *h = &wave->hdrs[wave->curhdr]; - - h->dwUser = 0; - mr = waveInAddBuffer (wave->hwi, h, sizeof (*h)); - if (mr != MMSYSERR_NOERROR) { - winwave_logerr (mr, "waveInAddBuffer(%d)", wave->curhdr); - } - wave->curhdr = (wave->curhdr + 1) % conf.adc_headers; - samples -= conf.adc_samples; - } -} - -static int winwave_init_in (HWVoiceIn *hw, struct audsettings *as) -{ - int i; - int err; - MMRESULT mr; - WAVEFORMATEX wfx; - WaveVoiceIn *wave; - - wave = (WaveVoiceIn *) hw; - - InitializeCriticalSection (&wave->crit_sect); - - err = waveformat_from_audio_settings (&wfx, as); - if (err) { - goto err0; - } - - mr = waveInOpen (&wave->hwi, WAVE_MAPPER, &wfx, - (DWORD_PTR) winwave_callback_in, - (DWORD_PTR) wave, CALLBACK_FUNCTION); - if (mr != MMSYSERR_NOERROR) { - winwave_logerr (mr, "waveInOpen"); - goto err1; - } - - wave->hdrs = audio_calloc (AUDIO_FUNC, conf.dac_headers, - sizeof (*wave->hdrs)); - if (!wave->hdrs) { - goto err2; - } - - audio_pcm_init_info (&hw->info, as); - hw->samples = conf.adc_samples * conf.adc_headers; - wave->avail = 0; - - wave->pcm_buf = audio_calloc (AUDIO_FUNC, conf.adc_samples, - conf.adc_headers << hw->info.shift); - if (!wave->pcm_buf) { - goto err3; - } - - for (i = 0; i < conf.adc_headers; ++i) { - WAVEHDR *h = &wave->hdrs[i]; - - h->dwUser = 0; - h->dwBufferLength = conf.adc_samples << hw->info.shift; - h->lpData = advance (wave->pcm_buf, i * h->dwBufferLength); - h->dwFlags = 0; - - mr = waveInPrepareHeader (wave->hwi, h, sizeof (*h)); - if (mr != MMSYSERR_NOERROR) { - winwave_logerr (mr, "waveInPrepareHeader(%d)", i); - goto err4; - } - } - - wave->paused = 1; - winwave_add_buffers (wave, hw->samples); - return 0; - - err4: - g_free (wave->pcm_buf); - err3: - g_free (wave->hdrs); - err2: - winwave_anal_close_in (wave); - err1: - err0: - return -1; -} - -static void winwave_fini_in (HWVoiceIn *hw) -{ - int i; - MMRESULT mr; - WaveVoiceIn *wave = (WaveVoiceIn *) hw; - - mr = waveInReset (wave->hwi); - if (mr != MMSYSERR_NOERROR) { - winwave_logerr (mr, "waveInReset"); - } - - for (i = 0; i < conf.adc_headers; ++i) { - mr = waveInUnprepareHeader (wave->hwi, &wave->hdrs[i], - sizeof (wave->hdrs[i])); - if (mr != MMSYSERR_NOERROR) { - winwave_logerr (mr, "waveInUnprepareHeader(%d)", i); - } - } - - winwave_anal_close_in (wave); - - if (wave->event) { - qemu_del_wait_object (wave->event, winwave_poll, wave); - if (!CloseHandle (wave->event)) { - dolog ("ADC CloseHandle failed %lx\n", GetLastError ()); - } - wave->event = NULL; - } - - g_free (wave->pcm_buf); - wave->pcm_buf = NULL; - - g_free (wave->hdrs); - wave->hdrs = NULL; -} - -static int winwave_run_in (HWVoiceIn *hw) -{ - WaveVoiceIn *wave = (WaveVoiceIn *) hw; - int live = audio_pcm_hw_get_live_in (hw); - int dead = hw->samples - live; - int decr, ret; - - if (!dead) { - return 0; - } - - EnterCriticalSection (&wave->crit_sect); - { - decr = audio_MIN (dead, wave->avail); - wave->avail -= decr; - } - LeaveCriticalSection (&wave->crit_sect); - - ret = decr; - while (decr) { - int left = hw->samples - hw->wpos; - int conv = audio_MIN (left, decr); - hw->conv (hw->conv_buf + hw->wpos, - advance (wave->pcm_buf, wave->rpos << hw->info.shift), - conv); - - wave->rpos = (wave->rpos + conv) % hw->samples; - hw->wpos = (hw->wpos + conv) % hw->samples; - decr -= conv; - } - - winwave_add_buffers (wave, ret); - return ret; -} - -static int winwave_read (SWVoiceIn *sw, void *buf, int size) -{ - return audio_pcm_sw_read (sw, buf, size); -} - -static int winwave_ctl_in (HWVoiceIn *hw, int cmd, ...) -{ - MMRESULT mr; - WaveVoiceIn *wave = (WaveVoiceIn *) hw; - - switch (cmd) { - case VOICE_ENABLE: - { - va_list ap; - int poll_mode; - - va_start (ap, cmd); - poll_mode = va_arg (ap, int); - va_end (ap); - - if (poll_mode && !wave->event) { - wave->event = CreateEvent (NULL, TRUE, TRUE, NULL); - if (!wave->event) { - dolog ("ADC CreateEvent: %lx, poll mode will be disabled\n", - GetLastError ()); - } - } - - if (wave->event) { - int ret; - - ret = qemu_add_wait_object (wave->event, winwave_poll, wave); - hw->poll_mode = (ret == 0); - } - else { - hw->poll_mode = 0; - } - if (wave->paused) { - mr = waveInStart (wave->hwi); - if (mr != MMSYSERR_NOERROR) { - winwave_logerr (mr, "waveInStart"); - } - wave->paused = 0; - } - } - return 0; - - case VOICE_DISABLE: - if (!wave->paused) { - mr = waveInStop (wave->hwi); - if (mr != MMSYSERR_NOERROR) { - winwave_logerr (mr, "waveInStop"); - } - else { - wave->paused = 1; - } - } - if (wave->event) { - qemu_del_wait_object (wave->event, winwave_poll, wave); - } - return 0; - } - return 0; -} - -static void *winwave_audio_init (void) -{ - return &conf; -} - -static void winwave_audio_fini (void *opaque) -{ - (void) opaque; -} - -static struct audio_option winwave_options[] = { - { - .name = "DAC_HEADERS", - .tag = AUD_OPT_INT, - .valp = &conf.dac_headers, - .descr = "DAC number of headers", - }, - { - .name = "DAC_SAMPLES", - .tag = AUD_OPT_INT, - .valp = &conf.dac_samples, - .descr = "DAC number of samples per header", - }, - { - .name = "ADC_HEADERS", - .tag = AUD_OPT_INT, - .valp = &conf.adc_headers, - .descr = "ADC number of headers", - }, - { - .name = "ADC_SAMPLES", - .tag = AUD_OPT_INT, - .valp = &conf.adc_samples, - .descr = "ADC number of samples per header", - }, - { /* End of list */ } -}; - -static struct audio_pcm_ops winwave_pcm_ops = { - .init_out = winwave_init_out, - .fini_out = winwave_fini_out, - .run_out = winwave_run_out, - .write = winwave_write, - .ctl_out = winwave_ctl_out, - .init_in = winwave_init_in, - .fini_in = winwave_fini_in, - .run_in = winwave_run_in, - .read = winwave_read, - .ctl_in = winwave_ctl_in -}; - -struct audio_driver winwave_audio_driver = { - .name = "winwave", - .descr = "Windows Waveform Audio http://msdn.microsoft.com", - .options = winwave_options, - .init = winwave_audio_init, - .fini = winwave_audio_fini, - .pcm_ops = &winwave_pcm_ops, - .can_be_default = 1, - .max_voices_out = INT_MAX, - .max_voices_in = INT_MAX, - .voice_size_out = sizeof (WaveVoiceOut), - .voice_size_in = sizeof (WaveVoiceIn) -}; |