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

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:
        !           225:     qemu_free (wave->pcm_buf);
        !           226:  err3:
        !           227:     qemu_free (wave->hdrs);
        !           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: 
        !           313:     qemu_free (wave->pcm_buf);
        !           314:     wave->pcm_buf = NULL;
        !           315: 
        !           316:     qemu_free (wave->hdrs);
        !           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:
        !           514:     qemu_free (wave->pcm_buf);
        !           515:  err3:
        !           516:     qemu_free (wave->hdrs);
        !           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: 
        !           553:     qemu_free (wave->pcm_buf);
        !           554:     wave->pcm_buf = NULL;
        !           555: 
        !           556:     qemu_free (wave->hdrs);
        !           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),
        !           584:                   conv,
        !           585:                   &nominal_volume);
        !           586: 
        !           587:         wave->rpos = (wave->rpos + conv) % hw->samples;
        !           588:         hw->wpos = (hw->wpos + conv) % hw->samples;
        !           589:         decr -= conv;
        !           590:     }
        !           591: 
        !           592:     winwave_add_buffers (wave, ret);
        !           593:     return ret;
        !           594: }
        !           595: 
        !           596: static int winwave_read (SWVoiceIn *sw, void *buf, int size)
        !           597: {
        !           598:     return audio_pcm_sw_read (sw, buf, size);
        !           599: }
        !           600: 
        !           601: static int winwave_ctl_in (HWVoiceIn *hw, int cmd, ...)
        !           602: {
        !           603:     MMRESULT mr;
        !           604:     WaveVoiceIn *wave = (WaveVoiceIn *) hw;
        !           605: 
        !           606:     switch (cmd) {
        !           607:     case VOICE_ENABLE:
        !           608:         {
        !           609:             va_list ap;
        !           610:             int poll_mode;
        !           611: 
        !           612:             va_start (ap, cmd);
        !           613:             poll_mode = va_arg (ap, int);
        !           614:             va_end (ap);
        !           615: 
        !           616:             if (poll_mode && !wave->event) {
        !           617:                 wave->event = CreateEvent (NULL, TRUE, TRUE, NULL);
        !           618:                 if (!wave->event) {
        !           619:                     dolog ("ADC CreateEvent: %lx, poll mode will be disabled\n",
        !           620:                            GetLastError ());
        !           621:                 }
        !           622:             }
        !           623: 
        !           624:             if (wave->event) {
        !           625:                 int ret;
        !           626: 
        !           627:                 ret = qemu_add_wait_object (wave->event, winwave_poll, wave);
        !           628:                 hw->poll_mode = (ret == 0);
        !           629:             }
        !           630:             else {
        !           631:                 hw->poll_mode = 0;
        !           632:             }
        !           633:             if (wave->paused) {
        !           634:                 mr = waveInStart (wave->hwi);
        !           635:                 if (mr != MMSYSERR_NOERROR) {
        !           636:                     winwave_logerr (mr, "waveInStart");
        !           637:                 }
        !           638:                 wave->paused = 0;
        !           639:             }
        !           640:         }
        !           641:         return 0;
        !           642: 
        !           643:     case VOICE_DISABLE:
        !           644:         if (!wave->paused) {
        !           645:             mr = waveInStop (wave->hwi);
        !           646:             if (mr != MMSYSERR_NOERROR) {
        !           647:                 winwave_logerr (mr, "waveInStop");
        !           648:             }
        !           649:             else {
        !           650:                 wave->paused = 1;
        !           651:             }
        !           652:         }
        !           653:         if (wave->event) {
        !           654:             qemu_del_wait_object (wave->event, winwave_poll, wave);
        !           655:         }
        !           656:         return 0;
        !           657:     }
        !           658:     return 0;
        !           659: }
        !           660: 
        !           661: static void *winwave_audio_init (void)
        !           662: {
        !           663:     return &conf;
        !           664: }
        !           665: 
        !           666: static void winwave_audio_fini (void *opaque)
        !           667: {
        !           668:     (void) opaque;
        !           669: }
        !           670: 
        !           671: static struct audio_option winwave_options[] = {
        !           672:     {
        !           673:         .name        = "DAC_HEADERS",
        !           674:         .tag         = AUD_OPT_INT,
        !           675:         .valp        = &conf.dac_headers,
        !           676:         .descr       = "DAC number of headers",
        !           677:     },
        !           678:     {
        !           679:         .name        = "DAC_SAMPLES",
        !           680:         .tag         = AUD_OPT_INT,
        !           681:         .valp        = &conf.dac_samples,
        !           682:         .descr       = "DAC number of samples per header",
        !           683:     },
        !           684:     {
        !           685:         .name        = "ADC_HEADERS",
        !           686:         .tag         = AUD_OPT_INT,
        !           687:         .valp        = &conf.adc_headers,
        !           688:         .descr       = "ADC number of headers",
        !           689:     },
        !           690:     {
        !           691:         .name        = "ADC_SAMPLES",
        !           692:         .tag         = AUD_OPT_INT,
        !           693:         .valp        = &conf.adc_samples,
        !           694:         .descr       = "ADC number of samples per header",
        !           695:     },
        !           696:     { /* End of list */ }
        !           697: };
        !           698: 
        !           699: static struct audio_pcm_ops winwave_pcm_ops = {
        !           700:     .init_out = winwave_init_out,
        !           701:     .fini_out = winwave_fini_out,
        !           702:     .run_out  = winwave_run_out,
        !           703:     .write    = winwave_write,
        !           704:     .ctl_out  = winwave_ctl_out,
        !           705:     .init_in  = winwave_init_in,
        !           706:     .fini_in  = winwave_fini_in,
        !           707:     .run_in   = winwave_run_in,
        !           708:     .read     = winwave_read,
        !           709:     .ctl_in   = winwave_ctl_in
        !           710: };
        !           711: 
        !           712: struct audio_driver winwave_audio_driver = {
        !           713:     .name           = "winwave",
        !           714:     .descr          = "Windows Waveform Audio http://msdn.microsoft.com",
        !           715:     .options        = winwave_options,
        !           716:     .init           = winwave_audio_init,
        !           717:     .fini           = winwave_audio_fini,
        !           718:     .pcm_ops        = &winwave_pcm_ops,
        !           719:     .can_be_default = 1,
        !           720:     .max_voices_out = INT_MAX,
        !           721:     .max_voices_in  = INT_MAX,
        !           722:     .voice_size_out = sizeof (WaveVoiceOut),
        !           723:     .voice_size_in  = sizeof (WaveVoiceIn)
        !           724: };

unix.superglobalmegacorp.com

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