- Timestamp:
- Dec 1, 2014 1:27:17 PM (10 years ago)
- Location:
- trunk/src/VBox/Devices/Audio
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/dsound_template.h
r53393 r53417 169 169 static void dsound_fini_out (HWVoiceOut *hw) 170 170 { 171 HRESULT hr;172 171 DSoundVoiceOut *ds = (DSoundVoiceOut *) hw; 173 174 if (ds->FIELD) { 175 hr = glue (IFACE, _Stop) (ds->FIELD); 176 if (FAILED (hr)) { 177 dsound_logerr (hr, "Could not stop " NAME "\n"); 178 } 179 180 hr = glue (IFACE, _Release) (ds->FIELD); 181 if (FAILED (hr)) { 182 dsound_logerr (hr, "Could not release " NAME "\n"); 183 } 184 ds->FIELD = NULL; 185 } 172 dsoundPlayClose (ds); 173 ds->old_pos = 0; 174 ds->first_time = 1; 175 ds->playback_buffer_size = 0; 176 memset (&ds->as, 0, sizeof(ds->as)); 186 177 } 187 178 #endif … … 194 185 ds->last_read_pos = 0; 195 186 ds->capture_buffer_size = 0; 187 ds->dsound_capture = NULL; 196 188 ds->dsound_capture_buffer = NULL; 197 189 ds->as = *as; … … 209 201 static int dsound_init_out (HWVoiceOut *hw, audsettings_t *as) 210 202 { 211 int err;212 HRESULT hr;213 dsound *s = &glob_dsound;214 WAVEFORMATEX wfx;215 audsettings_t obt_as;216 const char *typ = "DAC";217 203 DSoundVoiceOut *ds = (DSoundVoiceOut *) hw; 218 DSBUFFERDESC bd; 219 DSBCAPS bc; 220 221 err = waveformat_from_audio_settings (&wfx, as); 222 if (err) { 223 return -1; 224 } 225 226 memset (&bd, 0, sizeof (bd)); 227 bd.dwSize = sizeof (bd); 228 bd.lpwfxFormat = &wfx; 229 bd.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2; 230 bd.dwBufferBytes = conf.bufsize_out; 231 hr = IDirectSound_CreateSoundBuffer ( 232 s->dsound, 233 &bd, 234 &ds->dsound_buffer, 235 NULL 236 ); 237 238 if (FAILED (hr)) { 239 dsound_logerr2 (hr, typ, "Could not create " NAME "\n"); 240 return -1; 241 } 242 243 hr = glue (IFACE, _GetFormat) (ds->FIELD, &wfx, sizeof (wfx), NULL); 244 if (FAILED (hr)) { 245 dsound_logerr2 (hr, typ, "Could not get " NAME " format\n"); 246 goto fail0; 247 } 248 249 #ifdef DEBUG_DSOUND 250 dolog (NAME "\n"); 251 print_wave_format (&wfx); 252 #endif 253 254 memset (&bc, 0, sizeof (bc)); 255 bc.dwSize = sizeof (bc); 256 257 hr = glue (IFACE, _GetCaps) (ds->FIELD, &bc); 258 if (FAILED (hr)) { 259 dsound_logerr2 (hr, typ, "Could not get " NAME " format\n"); 260 goto fail0; 261 } 262 263 err = waveformat_to_audio_settings (&wfx, &obt_as); 264 if (err) { 265 goto fail0; 266 } 267 204 205 ds->dsound = NULL; 206 ds->dsound_buffer = NULL; 207 ds->old_pos = 0; 268 208 ds->first_time = 1; 269 obt_as.endianness = 0; 270 audio_pcm_init_info (&hw->info, &obt_as); 271 272 if (bc.dwBufferBytes & hw->info.align) { 273 dolog ( 274 "GetCaps returned misaligned buffer size %ld, alignment %d\n", 275 bc.dwBufferBytes, hw->info.align + 1 276 ); 277 } 278 hw->samples = bc.dwBufferBytes >> hw->info.shift; 279 280 #ifdef DEBUG_DSOUND 281 dolog ("caps %ld, desc %ld\n", 282 bc.dwBufferBytes, bd.dwBufferBytes); 283 284 dolog ("bufsize %d, freq %d, chan %d, bits %d, sign %d\n", 285 hw->samples << hw->info.shift, 286 hw->info.freq, 287 hw->info.nchannels, 288 hw->info.bits, 289 hw->info.sign); 290 #endif 291 return 0; 292 293 fail0: 294 glue (dsound_fini_, TYPE) (hw); 295 return -1; 209 ds->playback_buffer_size = 0; 210 ds->as = *as; 211 212 /* Init default settings. */ 213 audio_pcm_init_info (&hw->info, &ds->as); 214 hw->samples = conf.bufsize_out >> hw->info.shift; 215 216 /* Try to open playback in case the device is already there. */ 217 dsoundPlayOpen (ds); 218 219 return 0; 296 220 } 297 221 #endif -
trunk/src/VBox/Devices/Audio/dsoundaudio.c
r53395 r53417 60 60 #include "audio_int.h" 61 61 62 /* #define DEBUG_DSOUND */63 64 62 #define DSLOGF(a) do { LogRel2(a); } while(0) 65 63 #define DSLOGREL(a) \ … … 79 77 int restore_retries; 80 78 int getstatus_retries; 81 int set_primary;82 79 int bufsize_in; 83 80 int bufsize_out; 84 audsettings_t settings;85 81 int latency_millis; 86 82 char *device_guid_out; … … 90 86 1, 91 87 1, 92 0,93 88 16384, 94 89 16384, 95 {96 44100,97 2,98 AUD_FMT_S1699 },100 90 10, 101 91 NULL, … … 104 94 105 95 typedef struct { 106 LPDIRECTSOUND dsound; 107 LPDIRECTSOUNDCAPTURE dsound_capture; 108 LPDIRECTSOUNDBUFFER dsound_primary_buffer; 109 audsettings_t settings; 96 RTUUID devguid_play; 97 LPCGUID devguidp_play; 110 98 RTUUID devguid_capture; 111 99 LPCGUID devguidp_capture; … … 116 104 typedef struct { 117 105 HWVoiceOut hw; 106 LPDIRECTSOUND dsound; 118 107 LPDIRECTSOUNDBUFFER dsound_buffer; 119 108 DWORD old_pos; 120 109 int first_time; 121 #ifdef DEBUG_DSOUND 122 DWORD old_ppos; 123 DWORD played; 124 DWORD mixed; 125 #endif 110 int playback_buffer_size; 111 audsettings_t as; 126 112 } DSoundVoiceOut; 127 113 … … 130 116 int last_read_pos; 131 117 int capture_buffer_size; 118 LPDIRECTSOUNDCAPTURE dsound_capture; 132 119 LPDIRECTSOUNDCAPTUREBUFFER dsound_capture_buffer; 133 120 audsettings_t as; 134 121 HRESULT hr_last_run_in; 135 122 } DSoundVoiceIn; 123 124 static void dsound_clear_sample (DSoundVoiceOut *ds); 136 125 137 126 static void dsound_log_hresult (HRESULT hr) … … 313 302 } 314 303 315 #ifdef DEBUG_DSOUND316 static void print_wave_format (WAVEFORMATEX *wfx)317 {318 dolog ("tag = %d\n", wfx->wFormatTag);319 dolog ("nChannels = %d\n", wfx->nChannels);320 dolog ("nSamplesPerSec = %ld\n", wfx->nSamplesPerSec);321 dolog ("nAvgBytesPerSec = %ld\n", wfx->nAvgBytesPerSec);322 dolog ("nBlockAlign = %d\n", wfx->nBlockAlign);323 dolog ("wBitsPerSample = %d\n", wfx->wBitsPerSample);324 dolog ("cbSize = %d\n", wfx->cbSize);325 }326 #endif327 328 304 static int dsound_restore_out (LPDIRECTSOUNDBUFFER dsb) 329 305 { … … 342 318 343 319 default: 344 dsound_logerr (hr, "Could not restore playback buffer\n");320 DSLOGREL(("DSound: restore playback buffer %Rhrc\n", hr)); 345 321 return -1; 346 322 } 347 323 } 348 324 349 dolog ("%d attempts to restore playback buffer failed\n", i);325 DSLOGF(("DSound: %d attempts to restore playback buffer failed\n", i)); 350 326 return -1; 351 327 } … … 444 420 } 445 421 446 static void dsoundCaptureInterfaceRelease (dsound *s) 447 { 448 if (s->dsound_capture) { 449 HRESULT hr = IDirectSoundCapture_Release (s->dsound_capture); 422 /* 423 * DirectSound playback 424 */ 425 426 static void dsoundPlayInterfaceRelease (DSoundVoiceOut *ds) 427 { 428 if (ds->dsound) { 429 IDirectSound_Release (ds->dsound); 430 ds->dsound = NULL; 431 } 432 } 433 434 static int dsoundPlayInterfaceCreate (DSoundVoiceOut *ds) 435 { 436 dsound *s = &glob_dsound; 437 438 HRESULT hr; 439 440 if (ds->dsound != NULL) { 441 DSLOGF(("DSound: DirectSound instance already exists\n")); 442 return 0; 443 } 444 445 hr = CoCreateInstance (&CLSID_DirectSound, NULL, CLSCTX_ALL, 446 &IID_IDirectSound, (void **) &ds->dsound); 447 if (FAILED (hr)) { 448 DSLOGREL(("DSound: DirectSound create instance %Rhrc\n", hr)); 449 } 450 else { 451 hr = IDirectSound_Initialize (ds->dsound, s->devguidp_play); 452 if (SUCCEEDED(hr)) { 453 HWND hwnd = GetDesktopWindow (); 454 hr = IDirectSound_SetCooperativeLevel (ds->dsound, hwnd, DSSCL_PRIORITY); 455 if (FAILED (hr)) { 456 DSLOGREL(("DSound: set cooperative level for window %p %Rhrc\n", hwnd, hr)); 457 } 458 } 450 459 if (FAILED (hr)) { 451 DSLOGF(("DSound: DirectSoundCapture release %Rhrc\n", hr)); 452 } 453 s->dsound_capture = NULL; 454 } 455 } 456 457 static int dsoundCaptureInterfaceCreate (dsound *s) 458 { 460 if (hr == DSERR_NODRIVER) { 461 DSLOGREL(("DSound: DirectSound playback is currently unavailable\n")); 462 } 463 else { 464 DSLOGREL(("DSound: DirectSound initialize %Rhrc\n", hr)); 465 } 466 dsoundPlayInterfaceRelease (ds); 467 } 468 } 469 470 return SUCCEEDED (hr)? 0: -1; 471 } 472 473 static void dsoundPlayClose (DSoundVoiceOut *ds) 474 { 475 dsound *s = &glob_dsound; 476 459 477 HRESULT hr; 460 478 461 if (s->dsound_capture != NULL) { 479 DSLOGF(("DSound: playback close %p buffer %p\n", ds, ds->dsound_buffer)); 480 481 if (ds->dsound_buffer) { 482 hr = IDirectSoundBuffer_Stop (ds->dsound_buffer); 483 if (FAILED (hr)) { 484 DSLOGREL(("DSound: playback close Stop %Rhrc\n", hr)); 485 } 486 487 IDirectSoundBuffer_Release (ds->dsound_buffer); 488 ds->dsound_buffer = NULL; 489 } 490 491 dsoundPlayInterfaceRelease (ds); 492 } 493 494 static int dsoundPlayOpen (DSoundVoiceOut *ds) 495 { 496 dsound *s = &glob_dsound; 497 498 int err; 499 HRESULT hr; 500 WAVEFORMATEX wfx; 501 DSBUFFERDESC bd; 502 DSBCAPS bc; 503 504 DSLOGF(("DSound: playback open %p size %d samples, freq %d, chan %d, bits %d, sign %d\n", 505 ds, 506 ds->hw.samples, 507 ds->hw.info.freq, 508 ds->hw.info.nchannels, 509 ds->hw.info.bits, 510 ds->hw.info.sign)); 511 512 if (ds->dsound_buffer != NULL) { 513 /* Should not happen but be forgiving. */ 514 DSLOGREL(("DSound: DirectSoundBuffer already exists\n")); 515 dsoundPlayClose (ds); 516 } 517 518 err = waveformat_from_audio_settings (&wfx, &ds->as); 519 if (err) { 520 return err; 521 } 522 523 err = dsoundPlayInterfaceCreate (ds); 524 if (err) { 525 return err; 526 } 527 528 memset (&bd, 0, sizeof (bd)); 529 bd.dwSize = sizeof (bd); 530 bd.lpwfxFormat = &wfx; 531 bd.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2; 532 bd.dwBufferBytes = ds->hw.samples << ds->hw.info.shift; 533 hr = IDirectSound_CreateSoundBuffer (ds->dsound, 534 &bd, &ds->dsound_buffer, NULL); 535 if (FAILED (hr)) { 536 DSLOGREL(("DSound: playback CreateSoundBuffer %Rhrc\n", hr)); 537 goto fail0; 538 } 539 540 /* Query the actual parameters. */ 541 542 hr = IDirectSoundBuffer_GetFormat (ds->dsound_buffer, &wfx, sizeof (wfx), NULL); 543 if (FAILED (hr)) { 544 DSLOGREL(("DSound: playback GetFormat %Rhrc\n", hr)); 545 goto fail0; 546 } 547 548 memset (&bc, 0, sizeof (bc)); 549 bc.dwSize = sizeof (bc); 550 hr = IDirectSoundBuffer_GetCaps (ds->dsound_buffer, &bc); 551 if (FAILED (hr)) { 552 DSLOGREL(("DSound: playback GetCaps %Rhrc\n", hr)); 553 goto fail0; 554 } 555 556 DSLOGF(("DSound: playback format: size %d bytes\n" 557 " tag = %d\n" 558 " nChannels = %d\n" 559 " nSamplesPerSec = %d\n" 560 " nAvgBytesPerSec = %d\n" 561 " nBlockAlign = %d\n" 562 " wBitsPerSample = %d\n" 563 " cbSize = %d\n", 564 bc.dwBufferBytes, 565 wfx.wFormatTag, 566 wfx.nChannels, 567 wfx.nSamplesPerSec, 568 wfx.nAvgBytesPerSec, 569 wfx.nBlockAlign, 570 wfx.wBitsPerSample, 571 wfx.cbSize)); 572 573 if (bc.dwBufferBytes & ds->hw.info.align) { 574 DSLOGREL(("DSound: playback GetCaps returned misaligned buffer size %ld, alignment %d\n", 575 bc.dwBufferBytes, ds->hw.info.align + 1)); 576 } 577 578 if (ds->hw.samples != 0 && ds->hw.samples != (bc.dwBufferBytes >> ds->hw.info.shift)) { 579 DSLOGREL(("DSound: playback buffer size mismatch dsound %d, hw %d bytes\n", 580 bc.dwBufferBytes, ds->hw.samples << ds->hw.info.shift)); 581 } 582 583 /* Initial state. 584 * dsoundPlayStart initializes part of it to make sure that Stop/Start continues with a correct 585 * playback buffer position. 586 */ 587 ds->playback_buffer_size = bc.dwBufferBytes >> ds->hw.info.shift; 588 DSLOGF(("DSound: playback open playback_buffer_size %d\n", ds->playback_buffer_size)); 589 590 return 0; 591 592 fail0: 593 dsoundPlayClose (ds); 594 return -1; 595 } 596 597 static int dsoundPlayGetStatus (DSoundVoiceOut *ds, DWORD *statusp) 598 { 599 HRESULT hr; 600 DWORD status; 601 int i; 602 603 if (ds->dsound_buffer != NULL) { 604 for (i = 0; i < RT_MAX(conf.getstatus_retries, 1); ++i) { 605 hr = IDirectSoundBuffer_GetStatus (ds->dsound_buffer, &status); 606 if (FAILED (hr)) { 607 DSLOGF(("DSound: playback start GetStatus %Rhrc\n", hr)); 608 break; 609 } 610 611 if ((status & DSBSTATUS_BUFFERLOST) == 0) { 612 break; 613 } 614 615 if (dsound_restore_out (ds->dsound_buffer)) { 616 hr = E_FAIL; 617 break; 618 } 619 } 620 } 621 else 622 { 623 hr = E_FAIL; 624 } 625 626 if (SUCCEEDED (hr)) { 627 *statusp = status; 628 return 0; 629 } 630 return -1; 631 } 632 633 static void dsoundPlayStop (DSoundVoiceOut *ds) 634 { 635 HRESULT hr; 636 DWORD status; 637 638 if (ds->dsound_buffer != NULL) { 639 /* This performs some restore, so call it anyway and ignore result. */ 640 dsoundPlayGetStatus (ds, &status); 641 642 hr = IDirectSoundBuffer_Stop (ds->dsound_buffer); 643 if (FAILED (hr)) { 644 DSLOGF(("DSound: stop playback buffer %Rhrc\n", hr)); 645 } 646 } 647 } 648 649 static int dsoundPlayStart (DSoundVoiceOut *ds) 650 { 651 HRESULT hr; 652 DWORD status; 653 654 if (ds->dsound_buffer != NULL) { 655 if (dsoundPlayGetStatus (ds, &status)) { 656 DSLOGF(("DSound: playback start GetStatus failed\n")); 657 hr = E_FAIL; 658 } 659 else { 660 if (status & DSBSTATUS_PLAYING) { 661 DSLOGF(("DSound: already playing\n")); 662 } 663 else { 664 dsound_clear_sample (ds); 665 666 /* Reinit the playback buffer position. */ 667 ds->first_time = 1; 668 669 DSLOGF(("DSound: playback start\n")); 670 671 hr = IDirectSoundBuffer_Play (ds->dsound_buffer, 0, 0, DSBPLAY_LOOPING); 672 if (FAILED (hr)) { 673 DSLOGREL(("DSound: playback start %Rhrc\n", hr)); 674 } 675 } 676 } 677 } 678 else { 679 hr = E_FAIL; 680 } 681 682 return SUCCEEDED (hr)? 0: -1; 683 } 684 685 /* 686 * DirectSoundCapture 687 */ 688 689 static void dsoundCaptureInterfaceRelease (DSoundVoiceIn *ds) 690 { 691 if (ds->dsound_capture) { 692 IDirectSoundCapture_Release (ds->dsound_capture); 693 ds->dsound_capture = NULL; 694 } 695 } 696 697 static int dsoundCaptureInterfaceCreate (DSoundVoiceIn *ds) 698 { 699 dsound *s = &glob_dsound; 700 701 HRESULT hr; 702 703 if (ds->dsound_capture != NULL) { 462 704 DSLOGF(("DSound: DirectSoundCapture instance already exists\n")); 463 return -1;705 return 0; 464 706 } 465 707 466 708 hr = CoCreateInstance (&CLSID_DirectSoundCapture, NULL, CLSCTX_ALL, 467 &IID_IDirectSoundCapture, (void **) & s->dsound_capture);709 &IID_IDirectSoundCapture, (void **) &ds->dsound_capture); 468 710 if (FAILED (hr)) { 469 711 DSLOGREL(("DSound: DirectSoundCapture create instance %Rhrc\n", hr)); 470 712 } 471 713 else { 472 hr = IDirectSoundCapture_Initialize ( s->dsound_capture, s->devguidp_capture);714 hr = IDirectSoundCapture_Initialize (ds->dsound_capture, s->devguidp_capture); 473 715 if (FAILED (hr)) { 474 716 if (hr == DSERR_NODRIVER) { 475 DSLOGREL(("DSound: DirectSound Capture notavailable\n"));717 DSLOGREL(("DSound: DirectSound capture is currently unavailable\n")); 476 718 } 477 719 else { 478 720 DSLOGREL(("DSound: DirectSoundCapture initialize %Rhrc\n", hr)); 479 721 } 480 dsoundCaptureInterfaceRelease ( s);722 dsoundCaptureInterfaceRelease (ds); 481 723 } 482 724 } … … 497 739 } 498 740 499 hr = IDirectSoundCaptureBuffer_Release (ds->dsound_capture_buffer); 500 if (FAILED (hr)) { 501 DSLOGF(("DSound: close capture buffer release %Rhrc\n", hr)); 502 } 741 IDirectSoundCaptureBuffer_Release (ds->dsound_capture_buffer); 503 742 ds->dsound_capture_buffer = NULL; 504 743 } 505 744 506 dsoundCaptureInterfaceRelease ( s);745 dsoundCaptureInterfaceRelease (ds); 507 746 } 508 747 … … 537 776 } 538 777 539 err = dsoundCaptureInterfaceCreate ( s);778 err = dsoundCaptureInterfaceCreate (ds); 540 779 if (err) { 541 780 return err; … … 546 785 bd.lpwfxFormat = &wfx; 547 786 bd.dwBufferBytes = ds->hw.samples << ds->hw.info.shift; 548 hr = IDirectSoundCapture_CreateCaptureBuffer ( s->dsound_capture,787 hr = IDirectSoundCapture_CreateCaptureBuffer (ds->dsound_capture, 549 788 &bd, &ds->dsound_capture_buffer, NULL); 550 789 … … 609 848 ds->last_read_pos = cpos >> ds->hw.info.shift; 610 849 ds->capture_buffer_size = bc.dwBufferBytes >> ds->hw.info.shift; 611 DSLOGF(("DSound: open last_read_pos %d, capture_buffer_size %d\n", ds->last_read_pos, ds->capture_buffer_size));850 DSLOGF(("DSound: capture open last_read_pos %d, capture_buffer_size %d\n", ds->last_read_pos, ds->capture_buffer_size)); 612 851 613 852 ds->hr_last_run_in = S_OK; … … 645 884 } 646 885 else { 886 /** @todo Fill the capture beffer with silence here. */ 887 888 DSLOGF(("DSound: capture start\n")); 647 889 hr = IDirectSoundCaptureBuffer_Start (ds->dsound_capture_buffer, DSCBSTART_LOOPING); 648 890 if (FAILED (hr)) { … … 664 906 #undef DSBTYPE_IN 665 907 666 static int dsound_get_status_out (LPDIRECTSOUNDBUFFER dsb, DWORD *statusp)667 {668 HRESULT hr;669 int i;670 671 for (i = 0; i < conf.getstatus_retries; ++i) {672 hr = IDirectSoundBuffer_GetStatus (dsb, statusp);673 if (FAILED (hr)) {674 dsound_logerr (hr, "Could not get playback buffer status\n");675 return -1;676 }677 678 if (*statusp & DSERR_BUFFERLOST) {679 if (dsound_restore_out (dsb)) {680 return -1;681 }682 continue;683 }684 break;685 }686 687 return 0;688 }689 690 static int dsound_get_status_in (LPDIRECTSOUNDCAPTUREBUFFER dscb,691 DWORD *statusp)692 {693 HRESULT hr;694 695 hr = IDirectSoundCaptureBuffer_GetStatus (dscb, statusp);696 if (FAILED (hr)) {697 dsound_logerr (hr, "Could not get capture buffer status\n");698 return -1;699 }700 701 return 0;702 }703 704 908 static void dsound_write_sample (HWVoiceOut *hw, uint8_t *dst, int dst_len) 705 909 { … … 719 923 if (src_len1) { 720 924 hw->clip (dst, src1, src_len1); 721 // mixeng_sniff_and_clear (hw, src1, dst, src_len1);722 925 } 723 926 … … 725 928 dst = advance (dst, src_len1 << hw->info.shift); 726 929 hw->clip (dst, src2, src_len2); 727 // mixeng_sniff_and_clear (hw, src2, dst, src_len2);728 930 } 729 931 … … 731 933 } 732 934 733 static void dsound_clear_sample ( HWVoiceOut *hw, LPDIRECTSOUNDBUFFER dsb)935 static void dsound_clear_sample (DSoundVoiceOut *ds) 734 936 { 735 937 int err; … … 738 940 739 941 err = dsound_lock_out ( 740 ds b,741 & hw->info,942 ds->dsound_buffer, 943 &ds->hw.info, 742 944 0, 743 hw->samples << hw->info.shift,945 ds->playback_buffer_size << ds->hw.info.shift, 744 946 &p1, &p2, 745 947 &blen1, &blen2, … … 750 952 } 751 953 752 len1 = blen1 >> hw->info.shift; 753 len2 = blen2 >> hw->info.shift; 754 755 #ifdef DEBUG_DSOUND 756 dolog ("clear %p,%ld,%ld %p,%ld,%ld\n", 757 p1, blen1, len1, 758 p2, blen2, len2); 759 #endif 954 len1 = blen1 >> ds->hw.info.shift; 955 len2 = blen2 >> ds->hw.info.shift; 760 956 761 957 if (p1 && len1) { 762 audio_pcm_info_clear_buf (& hw->info, p1, len1);958 audio_pcm_info_clear_buf (&ds->hw.info, p1, len1); 763 959 } 764 960 765 961 if (p2 && len2) { 766 audio_pcm_info_clear_buf (&hw->info, p2, len2); 767 } 768 769 dsound_unlock_out (dsb, p1, p2, blen1, blen2); 770 } 771 772 static void dsound_close (dsound *s) 773 { 774 HRESULT hr; 775 776 if (s->dsound_primary_buffer) { 777 hr = IDirectSoundBuffer_Release (s->dsound_primary_buffer); 778 if (FAILED (hr)) { 779 dsound_logerr (hr, "Could not release primary buffer\n"); 780 } 781 s->dsound_primary_buffer = NULL; 782 } 783 } 784 785 static int dsound_open (dsound *s) 786 { 787 int err; 788 HRESULT hr; 789 WAVEFORMATEX wfx; 790 DSBUFFERDESC dsbd; 791 HWND hwnd; 792 793 hwnd = GetDesktopWindow (); 794 hr = IDirectSound_SetCooperativeLevel ( 795 s->dsound, 796 hwnd, 797 DSSCL_PRIORITY 798 ); 799 800 if (FAILED (hr)) { 801 #ifndef VBOX 802 dsound_logerr (hr, "Could not set cooperative level for window %p\n", 803 hwnd); 804 #else 805 LogRel(("DSound: Could not set cooperative level for window %p\n", hwnd)); 806 dsound_log_hresult(hr); 807 #endif 808 return -1; 809 } 810 811 if (!conf.set_primary) { 812 return 0; 813 } 814 815 err = waveformat_from_audio_settings (&wfx, &conf.settings); 816 if (err) { 817 return -1; 818 } 819 820 memset (&dsbd, 0, sizeof (dsbd)); 821 dsbd.dwSize = sizeof (dsbd); 822 dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER; 823 dsbd.dwBufferBytes = 0; 824 dsbd.lpwfxFormat = NULL; 825 826 hr = IDirectSound_CreateSoundBuffer ( 827 s->dsound, 828 &dsbd, 829 &s->dsound_primary_buffer, 830 NULL 831 ); 832 if (FAILED (hr)) { 833 #ifndef VBOX 834 dsound_logerr (hr, "Could not create primary playback buffer\n"); 835 #else 836 LogRel(("DSound: Could not create primary playback buffer\n")); 837 dsound_log_hresult(hr); 838 #endif 839 return -1; 840 } 841 842 hr = IDirectSoundBuffer_SetFormat (s->dsound_primary_buffer, &wfx); 843 if (FAILED (hr)) { 844 #ifndef VBOX 845 dsound_logerr (hr, "Could not set primary playback buffer format\n"); 846 #else 847 LogRel(("DSound: Could not set primary playback buffer format\n")); 848 dsound_log_hresult(hr); 849 #endif 850 } 851 852 hr = IDirectSoundBuffer_GetFormat ( 853 s->dsound_primary_buffer, 854 &wfx, 855 sizeof (wfx), 856 NULL 857 ); 858 if (FAILED (hr)) { 859 #ifndef VBOX 860 dsound_logerr (hr, "Could not get primary playback buffer format\n"); 861 #else 862 LogRel(("DSound: Could not get primary playback buffer format\n")); 863 dsound_log_hresult(hr); 864 #endif 865 goto fail0; 866 } 867 868 #ifdef DEBUG_DSOUND 869 dolog ("Primary\n"); 870 print_wave_format (&wfx); 871 #endif 872 873 err = waveformat_to_audio_settings (&wfx, &s->settings); 874 if (err) { 875 goto fail0; 876 } 877 878 return 0; 879 880 fail0: 881 dsound_close (s); 882 return -1; 962 audio_pcm_info_clear_buf (&ds->hw.info, p2, len2); 963 } 964 965 dsound_unlock_out (ds->dsound_buffer, p1, p2, blen1, blen2); 883 966 } 884 967 885 968 static int dsound_ctl_out (HWVoiceOut *hw, int cmd, ...) 886 969 { 887 HRESULT hr;888 DWORD status;889 970 DSoundVoiceOut *ds = (DSoundVoiceOut *) hw; 890 LPDIRECTSOUNDBUFFER dsb = ds->dsound_buffer;891 892 if (!dsb) {893 dolog ("Attempt to control voice without a buffer\n");894 return 0;895 }896 971 897 972 switch (cmd) { 898 973 case VOICE_ENABLE: 899 if (dsound_get_status_out (dsb, &status)) { 900 return -1; 901 } 902 903 if (status & DSBSTATUS_PLAYING) { 904 dolog ("warning: Voice is already playing\n"); 905 return 0; 906 } 907 908 dsound_clear_sample (hw, dsb); 909 910 hr = IDirectSoundBuffer_Play (dsb, 0, 0, DSBPLAY_LOOPING); 911 if (FAILED (hr)) { 912 dsound_logerr (hr, "Could not start playing buffer\n"); 913 return -1; 914 } 915 break; 916 917 case VOICE_DISABLE: 918 if (dsound_get_status_out (dsb, &status)) { 919 return -1; 920 } 921 922 if (status & DSBSTATUS_PLAYING) { 923 hr = IDirectSoundBuffer_Stop (dsb); 924 if (FAILED (hr)) { 925 dsound_logerr (hr, "Could not stop playing buffer\n"); 974 /* Try to start playback. If it fails, then reopen and try again. */ 975 if (dsoundPlayStart (ds)) { 976 dsoundPlayClose (ds); 977 dsoundPlayOpen (ds); 978 979 if (dsoundPlayStart (ds)) { 926 980 return -1; 927 981 } 928 982 } 929 else { 930 dolog ("warning: Voice is not playing\n"); 931 } 983 break; 984 985 case VOICE_DISABLE: 986 dsoundPlayStop (ds); 932 987 break; 933 988 } … … 955 1010 956 1011 if (!dsb) { 957 dolog ("Attempt to run empty with playback buffer\n");1012 DSLOGF(("DSound: run_out no playback buffer\n")); 958 1013 return 0; 959 1014 } 960 1015 961 1016 hwshift = hw->info.shift; 962 bufsize = hw->samples<< hwshift;1017 bufsize = ds->playback_buffer_size << hwshift; 963 1018 964 1019 live = audio_pcm_hw_get_live_out (hw); … … 967 1022 dsb, 968 1023 &ppos, 969 ds->first_time ? &wpos : NULL1024 &wpos 970 1025 ); 971 1026 if (hr == DSERR_BUFFERLOST) { 972 1027 if (dsound_restore_out(dsb)) 973 1028 return 0; 974 hr = IDirectSoundBuffer_GetCurrentPosition(dsb, &ppos, ds->first_time ? &wpos : NULL);1029 hr = IDirectSoundBuffer_GetCurrentPosition(dsb, &ppos, &wpos); 975 1030 if (hr == DSERR_BUFFERLOST) 976 1031 return 0; // Avoid log flooding if the error is still there. 977 1032 } 978 1033 if (FAILED (hr)) { 979 dsound_logerr (hr, "Could not get playback buffer position\n");1034 DSLOGF(("DSound: get playback buffer position %Rhrc\n", hr)); 980 1035 return 0; 981 1036 } … … 986 1041 if (conf.latency_millis) { 987 1042 DWORD cur_blat; 988 1043 DWORD conf_blat; 1044 1045 conf_blat = millis_to_bytes (&hw->info, conf.latency_millis); 989 1046 cur_blat = audio_ring_dist (wpos, ppos, bufsize); 990 ds->first_time = 0;991 1047 old_pos = wpos; 992 old_pos +=993 millis_to_bytes (&hw->info, conf.latency_millis)- cur_blat;1048 if (conf_blat > cur_blat) /* Do not write before wpos. */ 1049 old_pos += conf_blat - cur_blat; 994 1050 old_pos %= bufsize; 995 1051 old_pos &= ~hw->info.align; … … 998 1054 old_pos = wpos; 999 1055 } 1000 #ifdef DEBUG_DSOUND 1001 ds->played = 0; 1002 ds->mixed = 0; 1003 #endif 1056 ds->first_time = 0; 1004 1057 } 1005 1058 else { 1006 1059 if (ds->old_pos == ppos) { 1007 #ifdef DEBUG_DSOUND 1008 dolog ("old_pos == ppos\n"); 1009 #endif 1060 /* Full buffer. */ 1010 1061 return 0; 1011 1062 } 1012 1063 1013 #ifdef DEBUG_DSOUND1014 ds->played += audio_ring_dist (ds->old_pos, ppos, bufsize);1015 #endif1016 1064 old_pos = ds->old_pos; 1017 1065 } … … 1027 1075 1028 1076 if (audio_bug (AUDIO_FUNC, len < 0 || len > bufsize)) { 1029 dolog ("len=%d bufsize=%d old_pos=%ld ppos=%ld\n",1030 len, bufsize, old_pos, ppos) ;1077 DSLOGF(("DSound: error len=%d bufsize=%d old_pos=%ld ppos=%ld\n", 1078 len, bufsize, old_pos, ppos)); 1031 1079 return 0; 1032 1080 } … … 1037 1085 } 1038 1086 1039 #ifdef DEBUG_DSOUND1040 ds->old_ppos = ppos;1041 #endif1042 1087 err = dsound_lock_out ( 1043 1088 dsb, … … 1068 1113 ds->old_pos = (old_pos + (decr << hwshift)) % bufsize; 1069 1114 1070 #ifdef DEBUG_DSOUND1071 ds->mixed += decr << hwshift;1072 1073 dolog ("played %lu mixed %lu diff %ld sec %f\n",1074 ds->played,1075 ds->mixed,1076 ds->mixed - ds->played,1077 abs (ds->mixed - ds->played) / (double) hw->info.bytes_per_second);1078 #endif1079 1115 return decr; 1080 1116 } … … 1206 1242 } 1207 1243 1244 static int dsoundIsAvailable (void) 1245 { 1246 LPDIRECTSOUND dsound; 1247 HRESULT hr = CoCreateInstance (&CLSID_DirectSound, NULL, CLSCTX_ALL, 1248 &IID_IDirectSound, (void **) &dsound); 1249 if (SUCCEEDED(hr)) { 1250 IDirectSound_Release (dsound); 1251 return 1; 1252 } 1253 1254 DSLOGREL(("DSound: is unavailable %Rhrc\n", hr)); 1255 return 0; 1256 } 1257 1208 1258 static void dsound_audio_fini (void *opaque) 1209 1259 { 1210 HRESULT hr;1211 1260 dsound *s = opaque; 1212 1213 if (!s->dsound) { 1214 goto dsound_audio_fini_exit; 1215 } 1216 1217 hr = IDirectSound_Release (s->dsound); 1218 if (FAILED (hr)) { 1219 dsound_logerr (hr, "Could not release DirectSound\n"); 1220 } 1221 s->dsound = NULL; 1222 1223 if (!s->dsound_capture) { 1224 goto dsound_audio_fini_exit; 1225 } 1226 1227 hr = IDirectSoundCapture_Release (s->dsound_capture); 1228 if (FAILED (hr)) { 1229 dsound_logerr (hr, "Could not release DirectSoundCapture\n"); 1230 } 1231 s->dsound_capture = NULL; 1232 1233 dsound_audio_fini_exit: 1261 NOREF(s); 1234 1262 CoUninitialize(); 1235 1263 } … … 1237 1265 static void *dsound_audio_init (void) 1238 1266 { 1239 int err;1240 1267 HRESULT hr; 1241 1268 dsound *s = &glob_dsound; 1242 RTUUID devguid;1243 LPCGUID devguidp;1244 1269 1245 1270 hr = CoInitializeEx (NULL, COINIT_MULTITHREADED); 1246 1271 if (FAILED (hr)) { 1247 #ifndef VBOX 1248 dsound_logerr (hr, "Could not initialize COM\n"); 1249 #else 1250 LogRel(("DSound: Could not initialize COM\n")); 1251 dsound_log_hresult(hr); 1252 #endif 1272 DSLOGREL(("DSound: COM initialize %Rhrc\n", hr)); 1253 1273 return NULL; 1254 1274 } 1255 1275 1256 hr = CoCreateInstance (1257 &CLSID_DirectSound,1258 NULL,1259 CLSCTX_ALL,1260 &IID_IDirectSound,1261 (void **) &s->dsound1262 );1263 if (FAILED (hr)) {1264 #ifndef VBOX1265 dsound_logerr (hr, "Could not create DirectSound instance\n");1266 #else1267 LogRel(("DSound: Could not create DirectSound instance\n"));1268 dsound_log_hresult(hr);1269 #endif1270 CoUninitialize();1271 return NULL;1272 }1273 1274 1276 if (conf.device_guid_out) { 1275 hr = RTUuidFromStr(&devguid, conf.device_guid_out);1276 if (FAILED ( hr)) {1277 int rc = RTUuidFromStr(&s->devguid_play, conf.device_guid_out); 1278 if (FAILED (rc)) { 1277 1279 LogRel(("DSound: Could not parse DirectSound output device GUID\n")); 1278 1280 } 1279 devguidp = (LPCGUID)&devguid;1281 s->devguidp_play = (LPCGUID)&s->devguid_play; 1280 1282 } else { 1281 devguidp = NULL; 1282 } 1283 hr = IDirectSound_Initialize (s->dsound, devguidp); 1284 if (FAILED (hr)) { 1285 #ifndef VBOX 1286 dsound_logerr (hr, "Could not initialize DirectSound\n"); 1287 #else 1288 LogRel(("DSound: Could not initialize DirectSound\n")); 1289 dsound_log_hresult(hr); 1290 #endif 1291 1292 hr = IDirectSound_Release (s->dsound); 1293 if (FAILED (hr)) { 1294 dsound_logerr (hr, "Could not release DirectSound\n"); 1295 } 1296 s->dsound = NULL; 1297 CoUninitialize(); 1298 return NULL; 1283 s->devguidp_play = NULL; 1299 1284 } 1300 1285 … … 1309 1294 } 1310 1295 1311 err = dsound_open (s); 1312 if (err) { 1313 dsound_audio_fini (s); 1314 return NULL; 1315 } 1316 1317 return s; 1296 /* Check that DSound interface is available. */ 1297 if (dsoundIsAvailable ()) 1298 return s; 1299 1300 dsound_audio_fini (s); 1301 return NULL; 1318 1302 } 1319 1303 … … 1325 1309 {"GetStatusRetries", AUD_OPT_INT, &conf.getstatus_retries, 1326 1310 "Number of times to attempt getting status of the buffer", NULL, 0}, 1327 {"SetPrimary", AUD_OPT_BOOL, &conf.set_primary,1328 "Set the parameters of primary buffer", NULL, 0},1329 1311 {"LatencyMillis", AUD_OPT_INT, &conf.latency_millis, 1330 1312 "(undocumented)", NULL, 0}, 1331 {"PrimaryFreq", AUD_OPT_INT, &conf.settings.freq,1332 "Primary buffer frequency", NULL, 0},1333 {"PrimaryChannels", AUD_OPT_INT, &conf.settings.nchannels,1334 "Primary buffer number of channels (1 - mono, 2 - stereo)", NULL, 0},1335 {"PrimaryFmt", AUD_OPT_FMT, &conf.settings.fmt,1336 "Primary buffer format", NULL, 0},1337 1313 {"BufsizeOut", AUD_OPT_INT, &conf.bufsize_out, 1338 1314 "(undocumented)", NULL, 0},
Note:
See TracChangeset
for help on using the changeset viewer.