winwave: ADC support
Signed-off-by: malc <av1474@comtv.ru>
This commit is contained in:
		
							parent
							
								
									cb4f03e874
								
							
						
					
					
						commit
						a58c16dc13
					
				| 
						 | 
				
			
			@ -15,9 +15,13 @@
 | 
			
		|||
static struct {
 | 
			
		||||
    int dac_headers;
 | 
			
		||||
    int dac_samples;
 | 
			
		||||
    int adc_headers;
 | 
			
		||||
    int adc_samples;
 | 
			
		||||
} conf = {
 | 
			
		||||
    .dac_headers = 4,
 | 
			
		||||
    .dac_samples = 1024
 | 
			
		||||
    .dac_samples = 1024,
 | 
			
		||||
    .adc_headers = 4,
 | 
			
		||||
    .adc_samples = 1024
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
| 
						 | 
				
			
			@ -33,6 +37,19 @@ typedef struct {
 | 
			
		|||
    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";
 | 
			
		||||
| 
						 | 
				
			
			@ -73,11 +90,11 @@ static void winwave_log_mmresult (MMRESULT mr)
 | 
			
		|||
        break;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
        AUD_log (AUDIO_CAP, "Reason: Unknown (MMRESULT %#x)\n", mr);
 | 
			
		||||
        dolog ("Reason: Unknown (MMRESULT %#x)\n", mr);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    AUD_log (AUDIO_CAP, "Reason: %s\n", str);
 | 
			
		||||
    dolog ("Reason: %s\n", str);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void GCC_FMT_ATTR (2, 3) winwave_logerr (
 | 
			
		||||
| 
						 | 
				
			
			@ -107,7 +124,7 @@ static void winwave_anal_close_out (WaveVoiceOut *wave)
 | 
			
		|||
    wave->hwo = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void CALLBACK winwave_callback (
 | 
			
		||||
static void CALLBACK winwave_callback_out (
 | 
			
		||||
    HWAVEOUT hwo,
 | 
			
		||||
    UINT msg,
 | 
			
		||||
    DWORD_PTR dwInstance,
 | 
			
		||||
| 
						 | 
				
			
			@ -130,8 +147,7 @@ static void CALLBACK winwave_callback (
 | 
			
		|||
                LeaveCriticalSection (&wave->crit_sect);
 | 
			
		||||
                if (wave->hw.poll_mode) {
 | 
			
		||||
                    if (!SetEvent (wave->event)) {
 | 
			
		||||
                        AUD_log (AUDIO_CAP, "SetEvent failed %lx\n",
 | 
			
		||||
                                 GetLastError ());
 | 
			
		||||
                        dolog ("DAC SetEvent failed %lx\n", GetLastError ());
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -143,7 +159,7 @@ static void CALLBACK winwave_callback (
 | 
			
		|||
        break;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
        AUD_log (AUDIO_CAP, "unknown wave callback msg %x\n", msg);
 | 
			
		||||
        dolog ("unknown wave out callback msg %x\n", msg);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -165,7 +181,7 @@ static int winwave_init_out (HWVoiceOut *hw, struct audsettings *as)
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    mr = waveOutOpen (&wave->hwo, WAVE_MAPPER, &wfx,
 | 
			
		||||
                      (DWORD_PTR) winwave_callback,
 | 
			
		||||
                      (DWORD_PTR) winwave_callback_out,
 | 
			
		||||
                      (DWORD_PTR) wave, CALLBACK_FUNCTION);
 | 
			
		||||
    if (mr != MMSYSERR_NOERROR) {
 | 
			
		||||
        winwave_logerr (mr, "waveOutOpen");
 | 
			
		||||
| 
						 | 
				
			
			@ -198,7 +214,7 @@ static int winwave_init_out (HWVoiceOut *hw, struct audsettings *as)
 | 
			
		|||
 | 
			
		||||
        mr = waveOutPrepareHeader (wave->hwo, h, sizeof (*h));
 | 
			
		||||
        if (mr != MMSYSERR_NOERROR) {
 | 
			
		||||
            winwave_logerr (mr, "waveOutPrepareHeader(%d)", wave->curhdr);
 | 
			
		||||
            winwave_logerr (mr, "waveOutPrepareHeader(%d)", i);
 | 
			
		||||
            goto err4;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -238,7 +254,7 @@ static int winwave_run_out (HWVoiceOut *hw, int live)
 | 
			
		|||
 | 
			
		||||
    doreset = hw->poll_mode && (wave->pending >= conf.dac_samples);
 | 
			
		||||
    if (doreset && !ResetEvent (wave->event)) {
 | 
			
		||||
        AUD_log (AUDIO_CAP, "ResetEvent failed %lx\n", GetLastError ());
 | 
			
		||||
        dolog ("DAC ResetEvent failed %lx\n", GetLastError ());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    while (wave->pending >= conf.dac_samples) {
 | 
			
		||||
| 
						 | 
				
			
			@ -259,10 +275,10 @@ static int winwave_run_out (HWVoiceOut *hw, int live)
 | 
			
		|||
    return decr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void winwave_poll_out (void *opaque)
 | 
			
		||||
static void winwave_poll (void *opaque)
 | 
			
		||||
{
 | 
			
		||||
    (void) opaque;
 | 
			
		||||
    audio_run ("winwave_poll_out");
 | 
			
		||||
    audio_run ("winwave_poll");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void winwave_fini_out (HWVoiceOut *hw)
 | 
			
		||||
| 
						 | 
				
			
			@ -287,9 +303,9 @@ static void winwave_fini_out (HWVoiceOut *hw)
 | 
			
		|||
    winwave_anal_close_out (wave);
 | 
			
		||||
 | 
			
		||||
    if (wave->event) {
 | 
			
		||||
        qemu_del_wait_object (wave->event, winwave_poll_out, wave);
 | 
			
		||||
        qemu_del_wait_object (wave->event, winwave_poll, wave);
 | 
			
		||||
        if (!CloseHandle (wave->event)) {
 | 
			
		||||
            AUD_log (AUDIO_CAP, "CloseHandle failed %lx\n", GetLastError ());
 | 
			
		||||
            dolog ("DAC CloseHandle failed %lx\n", GetLastError ());
 | 
			
		||||
        }
 | 
			
		||||
        wave->event = NULL;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -319,8 +335,7 @@ static int winwave_ctl_out (HWVoiceOut *hw, int cmd, ...)
 | 
			
		|||
            if (poll_mode && !wave->event) {
 | 
			
		||||
                wave->event = CreateEvent (NULL, TRUE, TRUE, NULL);
 | 
			
		||||
                if (!wave->event) {
 | 
			
		||||
                    AUD_log (AUDIO_CAP,
 | 
			
		||||
                             "CreateEvent: %lx, poll mode will be disabled\n",
 | 
			
		||||
                    dolog ("DAC CreateEvent: %lx, poll mode will be disabled\n",
 | 
			
		||||
                           GetLastError ());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -328,8 +343,7 @@ static int winwave_ctl_out (HWVoiceOut *hw, int cmd, ...)
 | 
			
		|||
            if (wave->event) {
 | 
			
		||||
                int ret;
 | 
			
		||||
 | 
			
		||||
                ret = qemu_add_wait_object (wave->event, winwave_poll_out,
 | 
			
		||||
                                            wave);
 | 
			
		||||
                ret = qemu_add_wait_object (wave->event, winwave_poll, wave);
 | 
			
		||||
                hw->poll_mode = (ret == 0);
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
| 
						 | 
				
			
			@ -356,13 +370,294 @@ static int winwave_ctl_out (HWVoiceOut *hw, int cmd, ...)
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (wave->event) {
 | 
			
		||||
            qemu_del_wait_object (wave->event, winwave_poll_out, wave);
 | 
			
		||||
            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:
 | 
			
		||||
    qemu_free (wave->pcm_buf);
 | 
			
		||||
 err3:
 | 
			
		||||
    qemu_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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    qemu_free (wave->pcm_buf);
 | 
			
		||||
    wave->pcm_buf = NULL;
 | 
			
		||||
 | 
			
		||||
    qemu_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,
 | 
			
		||||
                  &nominal_volume);
 | 
			
		||||
 | 
			
		||||
        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;
 | 
			
		||||
| 
						 | 
				
			
			@ -386,6 +681,18 @@ static struct audio_option winwave_options[] = {
 | 
			
		|||
        .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 */ }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -394,7 +701,12 @@ static struct audio_pcm_ops winwave_pcm_ops = {
 | 
			
		|||
    .fini_out = winwave_fini_out,
 | 
			
		||||
    .run_out  = winwave_run_out,
 | 
			
		||||
    .write    = winwave_write,
 | 
			
		||||
    .ctl_out  = winwave_ctl_out
 | 
			
		||||
    .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 = {
 | 
			
		||||
| 
						 | 
				
			
			@ -406,7 +718,7 @@ struct audio_driver winwave_audio_driver = {
 | 
			
		|||
    .pcm_ops        = &winwave_pcm_ops,
 | 
			
		||||
    .can_be_default = 1,
 | 
			
		||||
    .max_voices_out = INT_MAX,
 | 
			
		||||
    .max_voices_in  = 0,
 | 
			
		||||
    .max_voices_in  = INT_MAX,
 | 
			
		||||
    .voice_size_out = sizeof (WaveVoiceOut),
 | 
			
		||||
    .voice_size_in  = 0
 | 
			
		||||
    .voice_size_in  = sizeof (WaveVoiceIn)
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue