Annotation of qemu/audio/winwaveaudio.c, revision 1.1.1.3

1.1       root        1: /* public domain */
                      2: 
                      3: #include "qemu-common.h"
                      4: #include "sysemu.h"
                      5: #include "audio.h"
                      6: 
                      7: #define AUDIO_CAP "winwave"
                      8: #include "audio_int.h"
                      9: 
                     10: #include <windows.h>
                     11: #include <mmsystem.h>
                     12: 
                     13: #include "audio_win_int.h"
                     14: 
                     15: static struct {
                     16:     int dac_headers;
                     17:     int dac_samples;
                     18:     int adc_headers;
                     19:     int adc_samples;
                     20: } conf = {
                     21:     .dac_headers = 4,
                     22:     .dac_samples = 1024,
                     23:     .adc_headers = 4,
                     24:     .adc_samples = 1024
                     25: };
                     26: 
                     27: typedef struct {
                     28:     HWVoiceOut hw;
                     29:     HWAVEOUT hwo;
                     30:     WAVEHDR *hdrs;
                     31:     HANDLE event;
                     32:     void *pcm_buf;
                     33:     int avail;
                     34:     int pending;
                     35:     int curhdr;
                     36:     int paused;
                     37:     CRITICAL_SECTION crit_sect;
                     38: } WaveVoiceOut;
                     39: 
                     40: typedef struct {
                     41:     HWVoiceIn hw;
                     42:     HWAVEIN hwi;
                     43:     WAVEHDR *hdrs;
                     44:     HANDLE event;
                     45:     void *pcm_buf;
                     46:     int curhdr;
                     47:     int paused;
                     48:     int rpos;
                     49:     int avail;
                     50:     CRITICAL_SECTION crit_sect;
                     51: } WaveVoiceIn;
                     52: 
                     53: static void winwave_log_mmresult (MMRESULT mr)
                     54: {
                     55:     const char *str = "BUG";
                     56: 
                     57:     switch (mr) {
                     58:     case MMSYSERR_NOERROR:
                     59:         str = "Success";
                     60:         break;
                     61: 
                     62:     case MMSYSERR_INVALHANDLE:
                     63:         str = "Specified device handle is invalid";
                     64:         break;
                     65: 
                     66:     case MMSYSERR_BADDEVICEID:
                     67:         str = "Specified device id is out of range";
                     68:         break;
                     69: 
                     70:     case MMSYSERR_NODRIVER:
                     71:         str = "No device driver is present";
                     72:         break;
                     73: 
                     74:     case MMSYSERR_NOMEM:
                     75:         str = "Unable to allocate or locl memory";
                     76:         break;
                     77: 
                     78:     case WAVERR_SYNC:
                     79:         str = "Device is synchronous but waveOutOpen was called "
                     80:             "without using the WINWAVE_ALLOWSYNC flag";
                     81:         break;
                     82: 
                     83:     case WAVERR_UNPREPARED:
                     84:         str = "The data block pointed to by the pwh parameter "
                     85:             "hasn't been prepared";
                     86:         break;
                     87: 
                     88:     case WAVERR_STILLPLAYING:
                     89:         str = "There are still buffers in the queue";
                     90:         break;
                     91: 
                     92:     default:
                     93:         dolog ("Reason: Unknown (MMRESULT %#x)\n", mr);
                     94:         return;
                     95:     }
                     96: 
                     97:     dolog ("Reason: %s\n", str);
                     98: }
                     99: 
                    100: static void GCC_FMT_ATTR (2, 3) winwave_logerr (
                    101:     MMRESULT mr,
                    102:     const char *fmt,
                    103:     ...
                    104:     )
                    105: {
                    106:     va_list ap;
                    107: 
                    108:     va_start (ap, fmt);
                    109:     AUD_vlog (AUDIO_CAP, fmt, ap);
                    110:     va_end (ap);
                    111: 
                    112:     AUD_log (NULL, " failed\n");
                    113:     winwave_log_mmresult (mr);
                    114: }
                    115: 
                    116: static void winwave_anal_close_out (WaveVoiceOut *wave)
                    117: {
                    118:     MMRESULT mr;
                    119: 
                    120:     mr = waveOutClose (wave->hwo);
                    121:     if (mr != MMSYSERR_NOERROR) {
                    122:         winwave_logerr (mr, "waveOutClose");
                    123:     }
                    124:     wave->hwo = NULL;
                    125: }
                    126: 
                    127: static void CALLBACK winwave_callback_out (
                    128:     HWAVEOUT hwo,
                    129:     UINT msg,
                    130:     DWORD_PTR dwInstance,
                    131:     DWORD_PTR dwParam1,
                    132:     DWORD_PTR dwParam2
                    133:     )
                    134: {
                    135:     WaveVoiceOut *wave = (WaveVoiceOut *) dwInstance;
                    136: 
                    137:     switch (msg) {
                    138:     case WOM_DONE:
                    139:         {
                    140:             WAVEHDR *h = (WAVEHDR *) dwParam1;
                    141:             if (!h->dwUser) {
                    142:                 h->dwUser = 1;
                    143:                 EnterCriticalSection (&wave->crit_sect);
                    144:                 {
                    145:                     wave->avail += conf.dac_samples;
                    146:                 }
                    147:                 LeaveCriticalSection (&wave->crit_sect);
                    148:                 if (wave->hw.poll_mode) {
                    149:                     if (!SetEvent (wave->event)) {
                    150:                         dolog ("DAC SetEvent failed %lx\n", GetLastError ());
                    151:                     }
                    152:                 }
                    153:             }
                    154:         }
                    155:         break;
                    156: 
                    157:     case WOM_CLOSE:
                    158:     case WOM_OPEN:
                    159:         break;
                    160: 
                    161:     default:
                    162:         dolog ("unknown wave out callback msg %x\n", msg);
                    163:     }
                    164: }
                    165: 
                    166: static int winwave_init_out (HWVoiceOut *hw, struct audsettings *as)
                    167: {
                    168:     int i;
                    169:     int err;
                    170:     MMRESULT mr;
                    171:     WAVEFORMATEX wfx;
                    172:     WaveVoiceOut *wave;
                    173: 
                    174:     wave = (WaveVoiceOut *) hw;
                    175: 
                    176:     InitializeCriticalSection (&wave->crit_sect);
                    177: 
                    178:     err = waveformat_from_audio_settings (&wfx, as);
                    179:     if (err) {
                    180:         goto err0;
                    181:     }
                    182: 
                    183:     mr = waveOutOpen (&wave->hwo, WAVE_MAPPER, &wfx,
                    184:                       (DWORD_PTR) winwave_callback_out,
                    185:                       (DWORD_PTR) wave, CALLBACK_FUNCTION);
                    186:     if (mr != MMSYSERR_NOERROR) {
                    187:         winwave_logerr (mr, "waveOutOpen");
                    188:         goto err1;
                    189:     }
                    190: 
                    191:     wave->hdrs = audio_calloc (AUDIO_FUNC, conf.dac_headers,
                    192:                                sizeof (*wave->hdrs));
                    193:     if (!wave->hdrs) {
                    194:         goto err2;
                    195:     }
                    196: 
                    197:     audio_pcm_init_info (&hw->info, as);
                    198:     hw->samples = conf.dac_samples * conf.dac_headers;
                    199:     wave->avail = hw->samples;
                    200: 
                    201:     wave->pcm_buf = audio_calloc (AUDIO_FUNC, conf.dac_samples,
                    202:                                   conf.dac_headers << hw->info.shift);
                    203:     if (!wave->pcm_buf) {
                    204:         goto err3;
                    205:     }
                    206: 
                    207:     for (i = 0; i < conf.dac_headers; ++i) {
                    208:         WAVEHDR *h = &wave->hdrs[i];
                    209: 
                    210:         h->dwUser = 0;
                    211:         h->dwBufferLength = conf.dac_samples << hw->info.shift;
                    212:         h->lpData = advance (wave->pcm_buf, i * h->dwBufferLength);
                    213:         h->dwFlags = 0;
                    214: 
                    215:         mr = waveOutPrepareHeader (wave->hwo, h, sizeof (*h));
                    216:         if (mr != MMSYSERR_NOERROR) {
                    217:             winwave_logerr (mr, "waveOutPrepareHeader(%d)", i);
                    218:             goto err4;
                    219:         }
                    220:     }
                    221: 
                    222:     return 0;
                    223: 
                    224:  err4:
1.1.1.3 ! root      225:     g_free (wave->pcm_buf);
1.1       root      226:  err3:
1.1.1.3 ! root      227:     g_free (wave->hdrs);
1.1       root      228:  err2:
                    229:     winwave_anal_close_out (wave);
                    230:  err1:
                    231:  err0:
                    232:     return -1;
                    233: }
                    234: 
                    235: static int winwave_write (SWVoiceOut *sw, void *buf, int len)
                    236: {
                    237:     return audio_pcm_sw_write (sw, buf, len);
                    238: }
                    239: 
                    240: static int winwave_run_out (HWVoiceOut *hw, int live)
                    241: {
                    242:     WaveVoiceOut *wave = (WaveVoiceOut *) hw;
                    243:     int decr;
                    244:     int doreset;
                    245: 
                    246:     EnterCriticalSection (&wave->crit_sect);
                    247:     {
                    248:         decr = audio_MIN (live, wave->avail);
                    249:         decr = audio_pcm_hw_clip_out (hw, wave->pcm_buf, decr, wave->pending);
                    250:         wave->pending += decr;
                    251:         wave->avail -= decr;
                    252:     }
                    253:     LeaveCriticalSection (&wave->crit_sect);
                    254: 
                    255:     doreset = hw->poll_mode && (wave->pending >= conf.dac_samples);
                    256:     if (doreset && !ResetEvent (wave->event)) {
                    257:         dolog ("DAC ResetEvent failed %lx\n", GetLastError ());
                    258:     }
                    259: 
                    260:     while (wave->pending >= conf.dac_samples) {
                    261:         MMRESULT mr;
                    262:         WAVEHDR *h = &wave->hdrs[wave->curhdr];
                    263: 
                    264:         h->dwUser = 0;
                    265:         mr = waveOutWrite (wave->hwo, h, sizeof (*h));
                    266:         if (mr != MMSYSERR_NOERROR) {
                    267:             winwave_logerr (mr, "waveOutWrite(%d)", wave->curhdr);
                    268:             break;
                    269:         }
                    270: 
                    271:         wave->pending -= conf.dac_samples;
                    272:         wave->curhdr = (wave->curhdr + 1) % conf.dac_headers;
                    273:     }
                    274: 
                    275:     return decr;
                    276: }
                    277: 
                    278: static void winwave_poll (void *opaque)
                    279: {
                    280:     (void) opaque;
                    281:     audio_run ("winwave_poll");
                    282: }
                    283: 
                    284: static void winwave_fini_out (HWVoiceOut *hw)
                    285: {
                    286:     int i;
                    287:     MMRESULT mr;
                    288:     WaveVoiceOut *wave = (WaveVoiceOut *) hw;
                    289: 
                    290:     mr = waveOutReset (wave->hwo);
                    291:     if (mr != MMSYSERR_NOERROR) {
                    292:         winwave_logerr (mr, "waveOutReset");
                    293:     }
                    294: 
                    295:     for (i = 0; i < conf.dac_headers; ++i) {
                    296:         mr = waveOutUnprepareHeader (wave->hwo, &wave->hdrs[i],
                    297:                                      sizeof (wave->hdrs[i]));
                    298:         if (mr != MMSYSERR_NOERROR) {
                    299:             winwave_logerr (mr, "waveOutUnprepareHeader(%d)", i);
                    300:         }
                    301:     }
                    302: 
                    303:     winwave_anal_close_out (wave);
                    304: 
                    305:     if (wave->event) {
                    306:         qemu_del_wait_object (wave->event, winwave_poll, wave);
                    307:         if (!CloseHandle (wave->event)) {
                    308:             dolog ("DAC CloseHandle failed %lx\n", GetLastError ());
                    309:         }
                    310:         wave->event = NULL;
                    311:     }
                    312: 
1.1.1.3 ! root      313:     g_free (wave->pcm_buf);
1.1       root      314:     wave->pcm_buf = NULL;
                    315: 
1.1.1.3 ! root      316:     g_free (wave->hdrs);
1.1       root      317:     wave->hdrs = NULL;
                    318: }
                    319: 
                    320: static int winwave_ctl_out (HWVoiceOut *hw, int cmd, ...)
                    321: {
                    322:     MMRESULT mr;
                    323:     WaveVoiceOut *wave = (WaveVoiceOut *) hw;
                    324: 
                    325:     switch (cmd) {
                    326:     case VOICE_ENABLE:
                    327:         {
                    328:             va_list ap;
                    329:             int poll_mode;
                    330: 
                    331:             va_start (ap, cmd);
                    332:             poll_mode = va_arg (ap, int);
                    333:             va_end (ap);
                    334: 
                    335:             if (poll_mode && !wave->event) {
                    336:                 wave->event = CreateEvent (NULL, TRUE, TRUE, NULL);
                    337:                 if (!wave->event) {
                    338:                     dolog ("DAC CreateEvent: %lx, poll mode will be disabled\n",
                    339:                            GetLastError ());
                    340:                 }
                    341:             }
                    342: 
                    343:             if (wave->event) {
                    344:                 int ret;
                    345: 
                    346:                 ret = qemu_add_wait_object (wave->event, winwave_poll, wave);
                    347:                 hw->poll_mode = (ret == 0);
                    348:             }
                    349:             else {
                    350:                 hw->poll_mode = 0;
                    351:             }
                    352:             if (wave->paused) {
                    353:                 mr = waveOutRestart (wave->hwo);
                    354:                 if (mr != MMSYSERR_NOERROR) {
                    355:                     winwave_logerr (mr, "waveOutRestart");
                    356:                 }
                    357:                 wave->paused = 0;
                    358:             }
                    359:         }
                    360:         return 0;
                    361: 
                    362:     case VOICE_DISABLE:
                    363:         if (!wave->paused) {
                    364:             mr = waveOutPause (wave->hwo);
                    365:             if (mr != MMSYSERR_NOERROR) {
                    366:                 winwave_logerr (mr, "waveOutPause");
                    367:             }
                    368:             else {
                    369:                 wave->paused = 1;
                    370:             }
                    371:         }
                    372:         if (wave->event) {
                    373:             qemu_del_wait_object (wave->event, winwave_poll, wave);
                    374:         }
                    375:         return 0;
                    376:     }
                    377:     return -1;
                    378: }
                    379: 
                    380: static void winwave_anal_close_in (WaveVoiceIn *wave)
                    381: {
                    382:     MMRESULT mr;
                    383: 
                    384:     mr = waveInClose (wave->hwi);
                    385:     if (mr != MMSYSERR_NOERROR) {
                    386:         winwave_logerr (mr, "waveInClose");
                    387:     }
                    388:     wave->hwi = NULL;
                    389: }
                    390: 
                    391: static void CALLBACK winwave_callback_in (
                    392:     HWAVEIN *hwi,
                    393:     UINT msg,
                    394:     DWORD_PTR dwInstance,
                    395:     DWORD_PTR dwParam1,
                    396:     DWORD_PTR dwParam2
                    397:     )
                    398: {
                    399:     WaveVoiceIn *wave = (WaveVoiceIn *) dwInstance;
                    400: 
                    401:     switch (msg) {
                    402:     case WIM_DATA:
                    403:         {
                    404:             WAVEHDR *h = (WAVEHDR *) dwParam1;
                    405:             if (!h->dwUser) {
                    406:                 h->dwUser = 1;
                    407:                 EnterCriticalSection (&wave->crit_sect);
                    408:                 {
                    409:                     wave->avail += conf.adc_samples;
                    410:                 }
                    411:                 LeaveCriticalSection (&wave->crit_sect);
                    412:                 if (wave->hw.poll_mode) {
                    413:                     if (!SetEvent (wave->event)) {
                    414:                         dolog ("ADC SetEvent failed %lx\n", GetLastError ());
                    415:                     }
                    416:                 }
                    417:             }
                    418:         }
                    419:         break;
                    420: 
                    421:     case WIM_CLOSE:
                    422:     case WIM_OPEN:
                    423:         break;
                    424: 
                    425:     default:
                    426:         dolog ("unknown wave in callback msg %x\n", msg);
                    427:     }
                    428: }
                    429: 
                    430: static void winwave_add_buffers (WaveVoiceIn *wave, int samples)
                    431: {
                    432:     int doreset;
                    433: 
                    434:     doreset = wave->hw.poll_mode && (samples >= conf.adc_samples);
                    435:     if (doreset && !ResetEvent (wave->event)) {
                    436:         dolog ("ADC ResetEvent failed %lx\n", GetLastError ());
                    437:     }
                    438: 
                    439:     while (samples >= conf.adc_samples) {
                    440:         MMRESULT mr;
                    441:         WAVEHDR *h = &wave->hdrs[wave->curhdr];
                    442: 
                    443:         h->dwUser = 0;
                    444:         mr = waveInAddBuffer (wave->hwi, h, sizeof (*h));
                    445:         if (mr != MMSYSERR_NOERROR) {
                    446:             winwave_logerr (mr, "waveInAddBuffer(%d)", wave->curhdr);
                    447:         }
                    448:         wave->curhdr = (wave->curhdr + 1) % conf.adc_headers;
                    449:         samples -= conf.adc_samples;
                    450:     }
                    451: }
                    452: 
                    453: static int winwave_init_in (HWVoiceIn *hw, struct audsettings *as)
                    454: {
                    455:     int i;
                    456:     int err;
                    457:     MMRESULT mr;
                    458:     WAVEFORMATEX wfx;
                    459:     WaveVoiceIn *wave;
                    460: 
                    461:     wave = (WaveVoiceIn *) hw;
                    462: 
                    463:     InitializeCriticalSection (&wave->crit_sect);
                    464: 
                    465:     err = waveformat_from_audio_settings (&wfx, as);
                    466:     if (err) {
                    467:         goto err0;
                    468:     }
                    469: 
                    470:     mr = waveInOpen (&wave->hwi, WAVE_MAPPER, &wfx,
                    471:                      (DWORD_PTR) winwave_callback_in,
                    472:                      (DWORD_PTR) wave, CALLBACK_FUNCTION);
                    473:     if (mr != MMSYSERR_NOERROR) {
                    474:         winwave_logerr (mr, "waveInOpen");
                    475:         goto err1;
                    476:     }
                    477: 
                    478:     wave->hdrs = audio_calloc (AUDIO_FUNC, conf.dac_headers,
                    479:                                sizeof (*wave->hdrs));
                    480:     if (!wave->hdrs) {
                    481:         goto err2;
                    482:     }
                    483: 
                    484:     audio_pcm_init_info (&hw->info, as);
                    485:     hw->samples = conf.adc_samples * conf.adc_headers;
                    486:     wave->avail = 0;
                    487: 
                    488:     wave->pcm_buf = audio_calloc (AUDIO_FUNC, conf.adc_samples,
                    489:                                   conf.adc_headers << hw->info.shift);
                    490:     if (!wave->pcm_buf) {
                    491:         goto err3;
                    492:     }
                    493: 
                    494:     for (i = 0; i < conf.adc_headers; ++i) {
                    495:         WAVEHDR *h = &wave->hdrs[i];
                    496: 
                    497:         h->dwUser = 0;
                    498:         h->dwBufferLength = conf.adc_samples << hw->info.shift;
                    499:         h->lpData = advance (wave->pcm_buf, i * h->dwBufferLength);
                    500:         h->dwFlags = 0;
                    501: 
                    502:         mr = waveInPrepareHeader (wave->hwi, h, sizeof (*h));
                    503:         if (mr != MMSYSERR_NOERROR) {
                    504:             winwave_logerr (mr, "waveInPrepareHeader(%d)", i);
                    505:             goto err4;
                    506:         }
                    507:     }
                    508: 
                    509:     wave->paused = 1;
                    510:     winwave_add_buffers (wave, hw->samples);
                    511:     return 0;
                    512: 
                    513:  err4:
1.1.1.3 ! root      514:     g_free (wave->pcm_buf);
1.1       root      515:  err3:
1.1.1.3 ! root      516:     g_free (wave->hdrs);
1.1       root      517:  err2:
                    518:     winwave_anal_close_in (wave);
                    519:  err1:
                    520:  err0:
                    521:     return -1;
                    522: }
                    523: 
                    524: static void winwave_fini_in (HWVoiceIn *hw)
                    525: {
                    526:     int i;
                    527:     MMRESULT mr;
                    528:     WaveVoiceIn *wave = (WaveVoiceIn *) hw;
                    529: 
                    530:     mr = waveInReset (wave->hwi);
                    531:     if (mr != MMSYSERR_NOERROR) {
                    532:         winwave_logerr (mr, "waveInReset");
                    533:     }
                    534: 
                    535:     for (i = 0; i < conf.adc_headers; ++i) {
                    536:         mr = waveInUnprepareHeader (wave->hwi, &wave->hdrs[i],
                    537:                                      sizeof (wave->hdrs[i]));
                    538:         if (mr != MMSYSERR_NOERROR) {
                    539:             winwave_logerr (mr, "waveInUnprepareHeader(%d)", i);
                    540:         }
                    541:     }
                    542: 
                    543:     winwave_anal_close_in (wave);
                    544: 
                    545:     if (wave->event) {
                    546:         qemu_del_wait_object (wave->event, winwave_poll, wave);
                    547:         if (!CloseHandle (wave->event)) {
                    548:             dolog ("ADC CloseHandle failed %lx\n", GetLastError ());
                    549:         }
                    550:         wave->event = NULL;
                    551:     }
                    552: 
1.1.1.3 ! root      553:     g_free (wave->pcm_buf);
1.1       root      554:     wave->pcm_buf = NULL;
                    555: 
1.1.1.3 ! root      556:     g_free (wave->hdrs);
1.1       root      557:     wave->hdrs = NULL;
                    558: }
                    559: 
                    560: static int winwave_run_in (HWVoiceIn *hw)
                    561: {
                    562:     WaveVoiceIn *wave = (WaveVoiceIn *) hw;
                    563:     int live = audio_pcm_hw_get_live_in (hw);
                    564:     int dead = hw->samples - live;
                    565:     int decr, ret;
                    566: 
                    567:     if (!dead) {
                    568:         return 0;
                    569:     }
                    570: 
                    571:     EnterCriticalSection (&wave->crit_sect);
                    572:     {
                    573:         decr = audio_MIN (dead, wave->avail);
                    574:         wave->avail -= decr;
                    575:     }
                    576:     LeaveCriticalSection (&wave->crit_sect);
                    577: 
                    578:     ret = decr;
                    579:     while (decr) {
                    580:         int left = hw->samples - hw->wpos;
                    581:         int conv = audio_MIN (left, decr);
                    582:         hw->conv (hw->conv_buf + hw->wpos,
                    583:                   advance (wave->pcm_buf, wave->rpos << hw->info.shift),
1.1.1.2   root      584:                   conv);
1.1       root      585: 
                    586:         wave->rpos = (wave->rpos + conv) % hw->samples;
                    587:         hw->wpos = (hw->wpos + conv) % hw->samples;
                    588:         decr -= conv;
                    589:     }
                    590: 
                    591:     winwave_add_buffers (wave, ret);
                    592:     return ret;
                    593: }
                    594: 
                    595: static int winwave_read (SWVoiceIn *sw, void *buf, int size)
                    596: {
                    597:     return audio_pcm_sw_read (sw, buf, size);
                    598: }
                    599: 
                    600: static int winwave_ctl_in (HWVoiceIn *hw, int cmd, ...)
                    601: {
                    602:     MMRESULT mr;
                    603:     WaveVoiceIn *wave = (WaveVoiceIn *) hw;
                    604: 
                    605:     switch (cmd) {
                    606:     case VOICE_ENABLE:
                    607:         {
                    608:             va_list ap;
                    609:             int poll_mode;
                    610: 
                    611:             va_start (ap, cmd);
                    612:             poll_mode = va_arg (ap, int);
                    613:             va_end (ap);
                    614: 
                    615:             if (poll_mode && !wave->event) {
                    616:                 wave->event = CreateEvent (NULL, TRUE, TRUE, NULL);
                    617:                 if (!wave->event) {
                    618:                     dolog ("ADC CreateEvent: %lx, poll mode will be disabled\n",
                    619:                            GetLastError ());
                    620:                 }
                    621:             }
                    622: 
                    623:             if (wave->event) {
                    624:                 int ret;
                    625: 
                    626:                 ret = qemu_add_wait_object (wave->event, winwave_poll, wave);
                    627:                 hw->poll_mode = (ret == 0);
                    628:             }
                    629:             else {
                    630:                 hw->poll_mode = 0;
                    631:             }
                    632:             if (wave->paused) {
                    633:                 mr = waveInStart (wave->hwi);
                    634:                 if (mr != MMSYSERR_NOERROR) {
                    635:                     winwave_logerr (mr, "waveInStart");
                    636:                 }
                    637:                 wave->paused = 0;
                    638:             }
                    639:         }
                    640:         return 0;
                    641: 
                    642:     case VOICE_DISABLE:
                    643:         if (!wave->paused) {
                    644:             mr = waveInStop (wave->hwi);
                    645:             if (mr != MMSYSERR_NOERROR) {
                    646:                 winwave_logerr (mr, "waveInStop");
                    647:             }
                    648:             else {
                    649:                 wave->paused = 1;
                    650:             }
                    651:         }
                    652:         if (wave->event) {
                    653:             qemu_del_wait_object (wave->event, winwave_poll, wave);
                    654:         }
                    655:         return 0;
                    656:     }
                    657:     return 0;
                    658: }
                    659: 
                    660: static void *winwave_audio_init (void)
                    661: {
                    662:     return &conf;
                    663: }
                    664: 
                    665: static void winwave_audio_fini (void *opaque)
                    666: {
                    667:     (void) opaque;
                    668: }
                    669: 
                    670: static struct audio_option winwave_options[] = {
                    671:     {
                    672:         .name        = "DAC_HEADERS",
                    673:         .tag         = AUD_OPT_INT,
                    674:         .valp        = &conf.dac_headers,
                    675:         .descr       = "DAC number of headers",
                    676:     },
                    677:     {
                    678:         .name        = "DAC_SAMPLES",
                    679:         .tag         = AUD_OPT_INT,
                    680:         .valp        = &conf.dac_samples,
                    681:         .descr       = "DAC number of samples per header",
                    682:     },
                    683:     {
                    684:         .name        = "ADC_HEADERS",
                    685:         .tag         = AUD_OPT_INT,
                    686:         .valp        = &conf.adc_headers,
                    687:         .descr       = "ADC number of headers",
                    688:     },
                    689:     {
                    690:         .name        = "ADC_SAMPLES",
                    691:         .tag         = AUD_OPT_INT,
                    692:         .valp        = &conf.adc_samples,
                    693:         .descr       = "ADC number of samples per header",
                    694:     },
                    695:     { /* End of list */ }
                    696: };
                    697: 
                    698: static struct audio_pcm_ops winwave_pcm_ops = {
                    699:     .init_out = winwave_init_out,
                    700:     .fini_out = winwave_fini_out,
                    701:     .run_out  = winwave_run_out,
                    702:     .write    = winwave_write,
                    703:     .ctl_out  = winwave_ctl_out,
                    704:     .init_in  = winwave_init_in,
                    705:     .fini_in  = winwave_fini_in,
                    706:     .run_in   = winwave_run_in,
                    707:     .read     = winwave_read,
                    708:     .ctl_in   = winwave_ctl_in
                    709: };
                    710: 
                    711: struct audio_driver winwave_audio_driver = {
                    712:     .name           = "winwave",
                    713:     .descr          = "Windows Waveform Audio http://msdn.microsoft.com",
                    714:     .options        = winwave_options,
                    715:     .init           = winwave_audio_init,
                    716:     .fini           = winwave_audio_fini,
                    717:     .pcm_ops        = &winwave_pcm_ops,
                    718:     .can_be_default = 1,
                    719:     .max_voices_out = INT_MAX,
                    720:     .max_voices_in  = INT_MAX,
                    721:     .voice_size_out = sizeof (WaveVoiceOut),
                    722:     .voice_size_in  = sizeof (WaveVoiceIn)
                    723: };

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.