Changeset 79223aaeafe7ef625f08551700a6ae4d2a26e8b0
- Timestamp:
- 03/02/08 18:22:11 (6 months ago)
- git-parent:
- Files:
-
- modules/audio_output/waveout.c (modified) (37 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
modules/audio_output/waveout.c
rced125d r79223aa 32 32 #include <vlc/vlc.h> 33 33 #include <vlc_aout.h> 34 #include <vlc_charset.h> 34 35 35 36 #include <windows.h> … … 121 122 /* local functions */ 122 123 static void Probe ( aout_instance_t * ); 123 static int OpenWaveOut ( aout_instance_t *, int, int, int, int, vlc_bool_t ); 124 static int OpenWaveOutPCM( aout_instance_t *, int*, int, int, int, vlc_bool_t ); 124 static int OpenWaveOut ( aout_instance_t *, uint32_t, 125 int, int, int, int, vlc_bool_t ); 126 static int OpenWaveOutPCM( aout_instance_t *, uint32_t, 127 int*, int, int, int, vlc_bool_t ); 125 128 static int PlayWaveOut ( aout_instance_t *, HWAVEOUT, WAVEHDR *, 126 aout_buffer_t * );129 aout_buffer_t *, vlc_bool_t ); 127 130 128 131 static void CALLBACK WaveOutCallback ( HWAVEOUT, UINT, DWORD, DWORD, DWORD ); … … 132 135 static int VolumeGet( aout_instance_t *, audio_volume_t * ); 133 136 static int VolumeSet( aout_instance_t *, audio_volume_t ); 137 138 static int WaveOutClearDoneBuffers(aout_sys_t *p_sys); 139 140 static int ReloadWaveoutDevices( vlc_object_t *, char const *, 141 vlc_value_t, vlc_value_t, void * ); 142 static uint32_t findDeviceID(char *); 143 144 static const char psz_device_name_fmt[] = "%s ($%x,$%x)"; 145 146 static const char *ppsz_adev[] = { "wavemapper", }; 147 static const char *ppsz_adev_text[] = { N_("Microsoft Soundmapper") }; 148 149 134 150 135 151 /***************************************************************************** … … 140 156 "The option allows you to enable or disable the high-quality float32 " \ 141 157 "audio output mode (which is not well supported by some soundcards)." ) 158 #define DEVICE_TEXT N_("Select Audio Device") 159 #define DEVICE_LONG N_("Select special Audio device, or let windows "\ 160 "decide (default), change needs VLC restart "\ 161 "to apply.") 162 #define DEFAULT_AUDIO_DEVICE N_("Default Audio Device") 142 163 143 164 vlc_module_begin(); … … 148 169 set_subcategory( SUBCAT_AUDIO_AOUT ); 149 170 add_bool( "waveout-float32", 1, 0, FLOAT_TEXT, FLOAT_LONGTEXT, VLC_TRUE ); 171 172 add_string( "waveout-dev", "wavemapper", NULL, 173 DEVICE_TEXT, DEVICE_LONG, VLC_FALSE ); 174 change_string_list( ppsz_adev, ppsz_adev_text, ReloadWaveoutDevices ); 175 change_need_restart(); 176 change_action_add( ReloadWaveoutDevices, N_("Refresh list") ); 177 178 150 179 set_callbacks( Open, Close ); 151 180 vlc_module_end(); … … 159 188 struct aout_sys_t 160 189 { 190 uint32_t i_wave_device_id; /* ID of selected output device */ 191 161 192 HWAVEOUT h_waveout; /* handle to waveout instance */ 162 193 … … 167 198 notification_thread_t *p_notif; /* WaveOutThread id */ 168 199 HANDLE event; 200 HANDLE new_buffer_event; 201 202 // rental from alsa.c to synchronize startup of audiothread 203 int b_playing; /* playing status */ 204 mtime_t start_date; 205 206 int i_repeat_counter; 169 207 170 208 int i_buffer_size; … … 215 253 p_aout->b_die = VLC_FALSE; 216 254 255 256 /* 257 initialize/update Device selection List 258 */ 259 ReloadWaveoutDevices( p_this, "waveout-dev", val, val, NULL); 260 261 262 /* 263 check for configured audio device! 264 */ 265 char *psz_waveout_dev = var_CreateGetString( p_aout, "waveout-dev"); 266 267 p_aout->output.p_sys->i_wave_device_id = 268 findDeviceID( psz_waveout_dev ); 269 270 if(p_aout->output.p_sys->i_wave_device_id == WAVE_MAPPER) 271 { 272 if(psz_waveout_dev && 273 stricmp(psz_waveout_dev,"wavemapper")) 274 { 275 msg_Warn( p_aout, "configured audio device '%s' not available, "\ 276 "use default instead", psz_waveout_dev ); 277 } 278 } 279 if(psz_waveout_dev) free( psz_waveout_dev ); 280 281 282 WAVEOUTCAPS waveoutcaps; 283 if(waveOutGetDevCaps( p_aout->output.p_sys->i_wave_device_id, 284 &waveoutcaps, 285 sizeof(WAVEOUTCAPS)) == MMSYSERR_NOERROR) 286 { 287 /* log debug some infos about driver, to know who to blame 288 if it doesn't work */ 289 msg_Dbg( p_aout, "Drivername: %s", waveoutcaps.szPname); 290 msg_Dbg( p_aout, "Driver Version: %d.%d", 291 (waveoutcaps.vDriverVersion>>8)&255, 292 waveoutcaps.vDriverVersion & 255); 293 msg_Dbg( p_aout, "Manufacturer identifier: 0x%x", waveoutcaps.wMid ); 294 msg_Dbg( p_aout, "Product identifier: 0x%x", waveoutcaps.wPid ); 295 } 296 297 298 217 299 if( var_Type( p_aout, "audio-device" ) == 0 ) 218 300 { … … 223 305 { 224 306 /* Probe() has failed. */ 307 var_Destroy( p_aout, "waveout-device"); 225 308 free( p_aout->output.p_sys ); 226 309 return VLC_EGENERIC; 227 310 } 228 311 229 var_Create( p_aout, "waveout-float32", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );230 312 231 313 /* Open the device */ … … 234 316 p_aout->output.output.i_format = VLC_FOURCC('s','p','d','i'); 235 317 236 if( OpenWaveOut( p_aout, VLC_FOURCC('s','p','d','i'), 318 if( OpenWaveOut( p_aout, 319 p_aout->output.p_sys->i_wave_device_id, 320 VLC_FOURCC('s','p','d','i'), 237 321 p_aout->output.output.i_physical_channels, 238 322 aout_FormatNbChannels( &p_aout->output.output ), … … 281 365 } 282 366 283 if( OpenWaveOutPCM( p_aout, &p_aout->output.output.i_format, 367 if( OpenWaveOutPCM( p_aout, 368 p_aout->output.p_sys->i_wave_device_id, 369 &p_aout->output.output.i_format, 284 370 p_aout->output.output.i_physical_channels, 285 371 aout_FormatNbChannels( &p_aout->output.output ), … … 328 414 return 1; 329 415 } 416 p_aout->output.p_sys->i_repeat_counter = 0; 417 330 418 331 419 /* Zero the buffer. WinCE doesn't have calloc(). */ … … 338 426 p_aout->output.p_sys->p_notif->p_aout = p_aout; 339 427 p_aout->output.p_sys->event = CreateEvent( NULL, FALSE, FALSE, NULL ); 428 p_aout->output.p_sys->new_buffer_event = CreateEvent( NULL, FALSE, FALSE, NULL ); 429 430 /* define startpoint of playback on first call to play() 431 like alsa does (instead of playing a blank sample) */ 432 p_aout->output.p_sys->b_playing = 0; 433 p_aout->output.p_sys->start_date = 0; 434 340 435 341 436 /* Then launch the notification thread */ 342 437 if( vlc_thread_create( p_aout->output.p_sys->p_notif, 343 438 "waveOut Notification Thread", WaveOutThread, 344 VLC_THREAD_PRIORITY_ HIGHEST, VLC_FALSE ) )439 VLC_THREAD_PRIORITY_OUTPUT, VLC_FALSE ) ) 345 440 { 346 441 msg_Err( p_aout, "cannot create WaveOutThread" ); … … 354 449 p_aout->output.p_sys->waveheader[i].dwUser = 0; 355 450 } 356 PlayWaveOut( p_aout, p_aout->output.p_sys->h_waveout,357 &p_aout->output.p_sys->waveheader[0], NULL );358 451 359 452 return 0; … … 379 472 if( p_aout->output.output.i_physical_channels == i_physical_channels ) 380 473 { 381 if( OpenWaveOutPCM( p_aout, &i_format, 474 if( OpenWaveOutPCM( p_aout, 475 p_aout->output.p_sys->i_wave_device_id, 476 &i_format, 382 477 i_physical_channels, 6, 383 478 p_aout->output.output.i_rate, VLC_TRUE ) … … 385 480 { 386 481 val.i_int = AOUT_VAR_5_1; 387 text.psz_string = N_("5.1");482 text.psz_string = (char *)N_("5.1"); 388 483 var_Change( p_aout, "audio-device", 389 484 VLC_VAR_ADDCHOICE, &val, &text ); … … 398 493 == i_physical_channels ) 399 494 { 400 if( OpenWaveOutPCM( p_aout, &i_format, 495 if( OpenWaveOutPCM( p_aout, 496 p_aout->output.p_sys->i_wave_device_id, 497 &i_format, 401 498 i_physical_channels, 4, 402 499 p_aout->output.output.i_rate, VLC_TRUE ) … … 404 501 { 405 502 val.i_int = AOUT_VAR_2F2R; 406 text.psz_string = N_("2 Front 2 Rear");503 text.psz_string = (char *)N_("2 Front 2 Rear"); 407 504 var_Change( p_aout, "audio-device", 408 505 VLC_VAR_ADDCHOICE, &val, &text ); … … 413 510 /* Test for stereo support */ 414 511 i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT; 415 if( OpenWaveOutPCM( p_aout, &i_format, 512 if( OpenWaveOutPCM( p_aout, 513 p_aout->output.p_sys->i_wave_device_id, 514 &i_format, 416 515 i_physical_channels, 2, 417 516 p_aout->output.output.i_rate, VLC_TRUE ) … … 419 518 { 420 519 val.i_int = AOUT_VAR_STEREO; 421 text.psz_string = N_("Stereo");520 text.psz_string = (char *)N_("Stereo"); 422 521 var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text ); 423 522 msg_Dbg( p_aout, "device supports 2 channels" ); … … 426 525 /* Test for mono support */ 427 526 i_physical_channels = AOUT_CHAN_CENTER; 428 if( OpenWaveOutPCM( p_aout, &i_format, 527 if( OpenWaveOutPCM( p_aout, 528 p_aout->output.p_sys->i_wave_device_id, 529 &i_format, 429 530 i_physical_channels, 1, 430 531 p_aout->output.output.i_rate, VLC_TRUE ) … … 432 533 { 433 534 val.i_int = AOUT_VAR_MONO; 434 text.psz_string = N_("Mono");535 text.psz_string = (char *)N_("Mono"); 435 536 var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text ); 436 537 msg_Dbg( p_aout, "device supports 1 channel" ); … … 440 541 if ( AOUT_FMT_NON_LINEAR( &p_aout->output.output ) ) 441 542 { 442 if( OpenWaveOut( p_aout, VLC_FOURCC('s','p','d','i'), 543 if( OpenWaveOut( p_aout, 544 p_aout->output.p_sys->i_wave_device_id, 545 VLC_FOURCC('s','p','d','i'), 443 546 p_aout->output.output.i_physical_channels, 444 547 aout_FormatNbChannels( &p_aout->output.output ), … … 448 551 msg_Dbg( p_aout, "device supports A/52 over S/PDIF" ); 449 552 val.i_int = AOUT_VAR_SPDIF; 450 text.psz_string = N_("A/52 over S/PDIF");553 text.psz_string = (char *)N_("A/52 over S/PDIF"); 451 554 var_Change( p_aout, "audio-device", 452 555 VLC_VAR_ADDCHOICE, &val, &text ); … … 478 581 static void Play( aout_instance_t *_p_aout ) 479 582 { 583 if( !_p_aout->output.p_sys->b_playing ) 584 { 585 _p_aout->output.p_sys->b_playing = 1; 586 587 /* get the playing date of the first aout buffer */ 588 _p_aout->output.p_sys->start_date = 589 aout_FifoFirstDate( _p_aout, &_p_aout->output.fifo ); 590 591 msg_Dbg( _p_aout, "Wakeup sleeping output thread."); 592 593 /* wake up the audio output thread */ 594 SetEvent( _p_aout->output.p_sys->event ); 595 } else { 596 SetEvent( _p_aout->output.p_sys->new_buffer_event ); 597 } 480 598 } 481 599 … … 491 609 vlc_object_kill( p_aout ); 492 610 493 waveOutReset( p_sys->h_waveout ); 494 495 /* wake up the audio thread */ 611 /* wake up the audio thread, to recognize that p_aout died */ 496 612 SetEvent( p_sys->event ); 613 SetEvent( p_sys->new_buffer_event ); 614 497 615 vlc_thread_join( p_sys->p_notif ); 498 616 vlc_object_release( p_sys->p_notif ); 617 618 /* 619 kill the real output then - when the feed thread 620 is surely terminated! 621 old code could be too early in case that "feeding" 622 was running on termination 623 624 at this point now its sure, that there will be no new 625 data send to the driver, and we can cancel the last 626 running playbuffers 627 */ 628 MMRESULT result = waveOutReset( p_sys->h_waveout ); 629 if(result != MMSYSERR_NOERROR) 630 { 631 msg_Err( p_aout, "waveOutReset failed 0x%x", result ); 632 /* 633 now we must wait, that all buffers are played 634 because cancel doesn't work in this case... 635 */ 636 if(result == MMSYSERR_NOTSUPPORTED) 637 { 638 /* 639 clear currently played (done) buffers, 640 if returnvalue > 0 (means some buffer still playing) 641 wait for the driver event callback that one buffer 642 is finished with playing, and check again 643 the timeout of 5000ms is just, an emergency exit 644 of this loop, to avoid deadlock in case of other 645 (currently not known bugs, problems, errors cases?) 646 */ 647 while( 648 (WaveOutClearDoneBuffers( p_sys ) > 0) 649 && 650 (WaitForSingleObject( p_sys->event, 5000) == WAIT_OBJECT_0) 651 ) 652 { 653 msg_Dbg( p_aout, "Wait for waveout device..."); 654 } 655 } 656 } else { 657 WaveOutClearDoneBuffers( p_sys ); 658 } 659 660 /* now we can Close the device */ 661 if( waveOutClose( p_sys->h_waveout ) != MMSYSERR_NOERROR ) 662 { 663 msg_Err( p_aout, "waveOutClose failed" ); 664 } 665 666 /* 667 because so long, the waveout device is playing, the callback 668 could occur and need the events 669 */ 499 670 CloseHandle( p_sys->event ); 500 501 /* Close the device */ 502 if( waveOutClose( p_sys->h_waveout ) != MMSYSERR_NOERROR ) 503 { 504 msg_Err( p_aout, "waveOutClose failed" ); 505 } 671 CloseHandle( p_sys->new_buffer_event); 506 672 507 673 free( p_sys->p_silence_buffer ); … … 512 678 * OpenWaveOut: open the waveout sound device 513 679 ****************************************************************************/ 514 static int OpenWaveOut( aout_instance_t *p_aout, int i_format,680 static int OpenWaveOut( aout_instance_t *p_aout, uint32_t i_device_id, int i_format, 515 681 int i_channels, int i_nb_channels, int i_rate, 516 682 vlc_bool_t b_probe ) … … 579 745 } 580 746 747 if(!b_probe) { 748 msg_Dbg( p_aout, "OpenWaveDevice-ID: %u", i_device_id); 749 msg_Dbg( p_aout,"waveformat.Format.cbSize = %d", 750 waveformat.Format.cbSize); 751 msg_Dbg( p_aout,"waveformat.Format.wFormatTag = %u", 752 waveformat.Format.wFormatTag); 753 msg_Dbg( p_aout,"waveformat.Format.nChannels = %u", 754 waveformat.Format.nChannels); 755 msg_Dbg( p_aout,"waveformat.Format.nSamplesPerSec = %d", 756 (int)waveformat.Format.nSamplesPerSec); 757 msg_Dbg( p_aout,"waveformat.Format.nAvgBytesPerSec = %u", 758 (int)waveformat.Format.nAvgBytesPerSec); 759 msg_Dbg( p_aout,"waveformat.Format.nBlockAlign = %d", 760 waveformat.Format.nBlockAlign); 761 msg_Dbg( p_aout,"waveformat.Format.wBitsPerSample = %d", 762 waveformat.Format.wBitsPerSample); 763 msg_Dbg( p_aout,"waveformat.Samples.wValidBitsPerSample = %d", 764 waveformat.Samples.wValidBitsPerSample); 765 msg_Dbg( p_aout,"waveformat.Samples.wSamplesPerBlock = %d", 766 waveformat.Samples.wSamplesPerBlock); 767 msg_Dbg( p_aout,"waveformat.dwChannelMask = %lu", 768 waveformat.dwChannelMask); 769 } 770 581 771 /* Open the device */ 582 result = waveOutOpen( &p_aout->output.p_sys->h_waveout, WAVE_MAPPER,772 result = waveOutOpen( &p_aout->output.p_sys->h_waveout, i_device_id, 583 773 (WAVEFORMATEX *)&waveformat, 584 774 (DWORD_PTR)WaveOutCallback, (DWORD_PTR)p_aout, … … 619 809 * OpenWaveOutPCM: open a PCM waveout sound device 620 810 ****************************************************************************/ 621 static int OpenWaveOutPCM( aout_instance_t *p_aout, int *i_format,811 static int OpenWaveOutPCM( aout_instance_t *p_aout, uint32_t i_device_id, int *i_format, 622 812 int i_channels, int i_nb_channels, int i_rate, 623 813 vlc_bool_t b_probe ) 624 814 { 625 vlc_value_t val; 626 627 var_Get( p_aout, "waveout-float32", &val ); 628 629 if( !val.b_bool || OpenWaveOut( p_aout, VLC_FOURCC('f','l','3','2'), 815 vlc_bool_t b_use_float32 = var_CreateGetBool( p_aout, "waveout-float32"); 816 817 if( !b_use_float32 || OpenWaveOut( p_aout, i_device_id, VLC_FOURCC('f','l','3','2'), 630 818 i_channels, i_nb_channels, i_rate, b_probe ) 631 819 != VLC_SUCCESS ) 632 820 { 633 if ( OpenWaveOut( p_aout, VLC_FOURCC('s','1','6','l'),821 if ( OpenWaveOut( p_aout, i_device_id, VLC_FOURCC('s','1','6','l'), 634 822 i_channels, i_nb_channels, i_rate, b_probe ) 635 823 != VLC_SUCCESS ) … … 654 842 *****************************************************************************/ 655 843 static int PlayWaveOut( aout_instance_t *p_aout, HWAVEOUT h_waveout, 656 WAVEHDR *p_waveheader, aout_buffer_t *p_buffer ) 844 WAVEHDR *p_waveheader, aout_buffer_t *p_buffer, 845 vlc_bool_t b_spdif) 657 846 { 658 847 MMRESULT result; … … 660 849 /* Prepare the buffer */ 661 850 if( p_buffer != NULL ) 851 { 662 852 p_waveheader->lpData = p_buffer->p_buffer; 663 else 853 /* 854 copy the buffer to the silence buffer :) so in case we don't 855 get the next buffer fast enough (I will repeat this one a time 856 for AC3 / DTS and SPDIF this will sound better instead of 857 a hickup) 858 */ 859 if(b_spdif) 860 { 861 p_aout->p_libvlc->pf_memcpy( p_aout->output.p_sys->p_silence_buffer, 862 p_buffer->p_buffer, 863 p_aout->output.p_sys->i_buffer_size ); 864 p_aout->output.p_sys->i_repeat_counter = 2; 865 } 866 } else { 664 867 /* Use silence buffer instead */ 868 if(p_aout->output.p_sys->i_repeat_counter) 869 { 870 p_aout->output.p_sys->i_repeat_counter--; 871 if(!p_aout->output.p_sys->i_repeat_counter) 872 { 873 p_aout->p_libvlc->pf_memset( p_aout->output.p_sys->p_silence_buffer, 874 0x00, 875 p_aout->output.p_sys->i_buffer_size 876 ); 877 } 878 } 665 879 p_waveheader->lpData = p_aout->output.p_sys->p_silence_buffer; 880 } 666 881 667 882 p_waveheader->dwUser = p_buffer ? (DWORD_PTR)p_buffer : (DWORD_PTR)1; … … 712 927 713 928 /* Don't wake up the thread too much */ 714 if( i_queued_frames < FRAMES_NUM /2 )929 if( i_queued_frames <= FRAMES_NUM/2 ) 715 930 SetEvent( p_aout->output.p_sys->event ); 931 } 932 933 934 /**************************************************************************** 935 * WaveOutClearDoneBuffers: Clear all done marked buffers, and free aout_bufer 936 **************************************************************************** 937 * return value is the number of still playing buffers in the queue 938 ****************************************************************************/ 939 static int WaveOutClearDoneBuffers(aout_sys_t *p_sys) 940 { 941 WAVEHDR *p_waveheader = p_sys->waveheader; 942 int i_queued_frames = 0; 943 944 for( int i = 0; i < FRAMES_NUM; i++ ) 945 { 946 if( (p_waveheader[i].dwFlags & WHDR_DONE) && 947 p_waveheader[i].dwUser ) 948 { 949 aout_buffer_t *p_buffer = 950 (aout_buffer_t *)(p_waveheader[i].dwUser); 951 /* Unprepare and free the buffers which has just been played */ 952 waveOutUnprepareHeader( p_sys->h_waveout, &p_waveheader[i], 953 sizeof(WAVEHDR) ); 954 955 if( p_waveheader[i].dwUser != 1 ) 956 aout_BufferFree( p_buffer ); 957 958 p_waveheader[i].dwUser = 0; 959 } 960 961 /* Check if frame buf is available */ 962 if( !(p_waveheader[i].dwFlags & WHDR_DONE) ) 963 { 964 i_queued_frames++; 965 } 966 } 967 return i_queued_frames; 716 968 } 717 969 … … 731 983 int i, i_queued_frames; 732 984 vlc_bool_t b_sleek; 985 mtime_t next_date; 986 uint32_t i_buffer_length = 64; 733 987 734 988 /* We don't want any resampling when using S/PDIF */ 735 989 b_sleek = p_aout->output.output.i_format == VLC_FOURCC('s','p','d','i'); 736 990 737 while( 1 ) 738 { 739 WaitForSingleObject( p_sys->event, INFINITE ); 740 991 // wait for first call to "play()" 992 while( !p_sys->start_date && !p_aout->b_die ) 993 WaitForSingleObject( p_sys->event, INFINITE ); 994 if( p_aout->b_die ) 995 return; 996 997 msg_Dbg( p_aout, "will start to play in "I64Fd" us", 998 (p_sys->start_date - AOUT_PTS_TOLERANCE/4)-mdate()); 999 1000 // than wait a short time... before grabbing first frames 1001 mwait( p_sys->start_date - AOUT_PTS_TOLERANCE/4 ); 1002 1003 #define waveout_warn(msg) msg_Warn( p_aout, "aout_OutputNextBuffer no buffer "\ 1004 "got next_date=%d ms, "\ 1005 "%d frames to play, "\ 1006 "starving? %d, %s",(int)(next_date/(mtime_t)1000), \ 1007 i_queued_frames, \ 1008 p_aout->output.b_starving, msg); 1009 next_date = mdate(); 1010 1011 while( !p_aout->b_die ) 1012 { 741 1013 /* Cleanup and find out the current latency */ 742 i_queued_frames = 0; 743 for( i = 0; i < FRAMES_NUM; i++ ) 744 { 745 if( (p_waveheader[i].dwFlags & WHDR_DONE) && 746 p_waveheader[i].dwUser ) 747 { 748 aout_buffer_t *p_buffer = 749 (aout_buffer_t *)(p_waveheader[i].dwUser); 750 /* Unprepare and free the buffers which has just been played */ 751 waveOutUnprepareHeader( p_sys->h_waveout, &p_waveheader[i], 752 sizeof(WAVEHDR) ); 753 754 if( p_waveheader[i].dwUser != 1 ) 755 aout_BufferFree( p_buffer ); 756 757 p_waveheader[i].dwUser = 0; 758 } 759 760 /* Check if frame buf is available */ 761 if( !(p_waveheader[i].dwFlags & WHDR_DONE) ) 762 { 763 i_queued_frames++; 764 } 765 } 1014 i_queued_frames = WaveOutClearDoneBuffers( p_sys ); 766 1015 767 1016 if( p_aout->b_die ) return; … … 773 1022 if( p_waveheader[i].dwFlags & WHDR_DONE ) 774 1023 { 1024 // next_date = mdate() + 1000000 * i_queued_frames / 1025 // p_aout->output.output.i_rate * p_aout->output.i_nb_samples; 1026 1027 // the realtime has got our back-site:) to come in sync 1028 if(next_date < mdate()) 1029 next_date = mdate(); 1030 1031 775 1032 /* Take into account the latency */ 776 1033 p_buffer = aout_OutputNextBuffer( p_aout, 777 mdate() + 1000000 * i_queued_frames / 778 p_aout->output.output.i_rate * p_aout->output.i_nb_samples, 1034 next_date, 779 1035 b_sleek ); 1036 1037 if(!p_buffer) 1038 { 1039 #if 0 1040 msg_Dbg( p_aout, "aout_OutputNextBuffer no buffer "\ 1041 "got next_date=%d ms, "\ 1042 "%d frames to play, "\ 1043 "starving? %d",(int)(next_date/(mtime_t)1000), 1044 i_queued_frames, 1045 p_aout->output.b_starving); 1046 #endif 1047 if(p_aout->output.b_starving) 1048 { 1049 // means we are too early to request a new buffer? 1050 waveout_warn("waiting...") 1051 next_date = aout_FifoFirstDate( p_aout, &p_aout->output.fifo ); 1052 mwait( next_date - AOUT_PTS_TOLERANCE/4 ); 1053 next_date = mdate(); 1054 p_buffer = aout_OutputNextBuffer( p_aout, 1055 next_date, 1056 b_sleek 1057 ); 1058 } 1059 } 780 1060 781 1061 if( !p_buffer && i_queued_frames ) … … 783 1063 /* We aren't late so no need to play a blank sample */ 784 1064 break; 1065 } 1066 1067 if( p_buffer ) 1068 { 1069 mtime_t buffer_length = (p_buffer->end_date 1070 - p_buffer->start_date); 1071 next_date = next_date + buffer_length; 1072 i_buffer_length = buffer_length/1000; 785 1073 } 786 1074 … … 796 1084 797 1085 PlayWaveOut( p_aout, p_sys->h_waveout, 798 &p_waveheader[i], p_buffer );1086 &p_waveheader[i], p_buffer, b_sleek ); 799 1087 800 1088 i_queued_frames++; 801 1089 } 802 1090 } 803 } 1091 1092 if( p_aout->b_die ) return; 1093 1094 /* 1095 deal with the case that the loop didn't fillup the buffer to the 1096 max - instead of waiting that half the buffer is played before 1097 fillup the waveout buffers, wait only for the next sample buffer 1098 to arrive at the play method... 1099 1100 this will also avoid, that the last buffer is play until the 1101 end, and then trying to get more data, so it will also 1102 work - if the next buffer will arrive some ms before the 1103 last buffer is finished. 1104 */ 1105 if(i_queued_frames < FRAMES_NUM) 1106 WaitForSingleObject( p_sys->new_buffer_event, INFINITE ); 1107 else 1108 WaitForSingleObject( p_sys->event, INFINITE ); 1109 1110 } 1111 1112 #undef waveout_warn 804 1113 } 805 1114 … … 840 1149 return 0; 841 1150 } 1151 1152 1153 /* 1154 reload the configuration drop down list, of the Audio Devices 1155 */ 1156 static int ReloadWaveoutDevices( vlc_object_t *p_this, char const *psz_name, 1157 vlc_value_t newval, vlc_value_t oldval, void *data ) 1158 { 1159 int i; 1160 1161 module_config_t *p_item = config_FindConfig( p_this, psz_name ); 1162 if( !p_item ) return VLC_SUCCESS; 1163 1164 /* Clear-up the current list */ 1165 if( p_item->i_list ) 1166 { 1167 /* Keep the first entry */ 1168 for( i = 1; i < p_item->i_list; i++ ) 1169 { 1170 free((char *)(p_item->ppsz_list[i]) ); 1171 free((char *)(p_item->ppsz_list_text[i]) ); 1172 } 1173 /* TODO: Remove when no more needed */ 1174 p_item->ppsz_list[i] = NULL; 1175 p_item->ppsz_list_text[i] = NULL; 1176 } 1177 p_item->i_list = 1; 1178 1179 int wave_devices = waveOutGetNumDevs(); 1180 1181 p_item->ppsz_list = 1182 (char **)realloc( p_item->ppsz_list, 1183 (wave_devices+2) * sizeof(char *) ); 1184 p_item->ppsz_list_text = 1185 (char **)realloc( p_item->ppsz_list_text, 1186 (wave_devices+2) * sizeof(char *) ); 1187 1188 WAVEOUTCAPS caps; 1189 char sz_dev_name[MAXPNAMELEN+32]; 1190 int j=1; 1191 for(int i=0; i<wave_devices; i++) 1192 { 1193 if(waveOutGetDevCaps(i, &caps, sizeof(WAVEOUTCAPS)) 1194 == MMSYSERR_NOERROR) 1195 { 1196 sprintf(sz_dev_name,psz_device_name_fmt,caps.szPname, 1197 caps.wMid, 1198 caps.wPid 1199 ); 1200 p_item->ppsz_list[j] = strdup( sz_dev_name ); 1201 p_item->ppsz_list_text[j] = FromLocaleDup( sz_dev_name ); 1202 p_item->i_list++; 1203 j++; 1204 } 1205 1206 } 1207 p_item->ppsz_list[j] = NULL; 1208 p_item->ppsz_list_text[j] = NULL; 1209 1210 /* Signal change to the interface */ 1211 p_item->b_dirty = VLC_TRUE; 1212 1213 return VLC_SUCCESS; 1214 } 1215 1216 /* 1217 convert devicename to device ID for output 1218 if device not found return WAVE_MAPPER, so let 1219 windows decide which prefered audio device 1220 should be used. 1221 */ 1222 static uint32_t findDeviceID(char *psz_device_name) 1223 { 1224 if(!psz_device_name) 1225 return WAVE_MAPPER; 1226 1227 uint32_t wave_devices = waveOutGetNumDevs(); 1228 WAVEOUTCAPS caps; 1229 char sz_dev_name[MAXPNAMELEN+32]; 1230 for(uint32_t i=0; i<wave_devices; i++) 1231 { 1232 if(waveOutGetDevCaps(i, &caps, sizeof(WAVEOUTCAPS)) 1233 == MMSYSERR_NOERROR) 1234 { 1235 sprintf(sz_dev_name,psz_device_name_fmt,caps.szPname, 1236 caps.wMid, 1237 caps.wPid 1238 ); 1239 if(!stricmp(sz_dev_name,psz_device_name)) 1240 return i; 1241 } 1242 } 1243 1244 return WAVE_MAPPER; 1245 }
