1 /*****************************************************************************
2 * waveout.c : Windows waveOut plugin for vlc
3 *****************************************************************************
4 * Copyright (C) 2001 the VideoLAN team
7 * Authors: Gildas Bazin <gbazin@videolan.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
32 #include <vlc_common.h>
33 #include <vlc_plugin.h>
35 #include <vlc_charset.h>
40 #define FRAME_SIZE 4096 /* The size is in samples, not in bytes */
43 /*****************************************************************************
45 *****************************************************************************/
47 # define DWORD_PTR DWORD
48 # ifdef waveOutGetDevCaps
49 # undef waveOutGetDevCaps
50 MMRESULT WINAPI waveOutGetDevCaps(UINT, LPWAVEOUTCAPS, UINT);
54 #ifndef WAVE_FORMAT_IEEE_FLOAT
55 # define WAVE_FORMAT_IEEE_FLOAT 0x0003
58 #ifndef WAVE_FORMAT_DOLBY_AC3_SPDIF
59 # define WAVE_FORMAT_DOLBY_AC3_SPDIF 0x0092
62 #ifndef WAVE_FORMAT_EXTENSIBLE
63 #define WAVE_FORMAT_EXTENSIBLE 0xFFFE
66 #ifndef SPEAKER_FRONT_LEFT
67 # define SPEAKER_FRONT_LEFT 0x1
68 # define SPEAKER_FRONT_RIGHT 0x2
69 # define SPEAKER_FRONT_CENTER 0x4
70 # define SPEAKER_LOW_FREQUENCY 0x8
71 # define SPEAKER_BACK_LEFT 0x10
72 # define SPEAKER_BACK_RIGHT 0x20
73 # define SPEAKER_FRONT_LEFT_OF_CENTER 0x40
74 # define SPEAKER_FRONT_RIGHT_OF_CENTER 0x80
75 # define SPEAKER_BACK_CENTER 0x100
76 # define SPEAKER_SIDE_LEFT 0x200
77 # define SPEAKER_SIDE_RIGHT 0x400
78 # define SPEAKER_TOP_CENTER 0x800
79 # define SPEAKER_TOP_FRONT_LEFT 0x1000
80 # define SPEAKER_TOP_FRONT_CENTER 0x2000
81 # define SPEAKER_TOP_FRONT_RIGHT 0x4000
82 # define SPEAKER_TOP_BACK_LEFT 0x8000
83 # define SPEAKER_TOP_BACK_CENTER 0x10000
84 # define SPEAKER_TOP_BACK_RIGHT 0x20000
85 # define SPEAKER_RESERVED 0x80000000
88 #ifndef _WAVEFORMATEXTENSIBLE_
92 WORD wValidBitsPerSample; /* bits of precision */
93 WORD wSamplesPerBlock; /* valid if wBitsPerSample==0 */
94 WORD wReserved; /* If neither applies, set to zero. */
96 DWORD dwChannelMask; /* which channels are */
97 /* present in stream */
99 } WAVEFORMATEXTENSIBLE, *PWAVEFORMATEXTENSIBLE;
102 static const GUID __KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = {WAVE_FORMAT_IEEE_FLOAT, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
103 static const GUID __KSDATAFORMAT_SUBTYPE_PCM = {WAVE_FORMAT_PCM, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
104 static const GUID __KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF = {WAVE_FORMAT_DOLBY_AC3_SPDIF, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
106 /*****************************************************************************
108 *****************************************************************************/
109 static int Open ( vlc_object_t * );
110 static void Close ( vlc_object_t * );
111 static void Play ( aout_instance_t * );
113 /*****************************************************************************
114 * notification_thread_t: waveOut event thread
115 *****************************************************************************/
116 typedef struct notification_thread_t
119 aout_instance_t *p_aout;
121 } notification_thread_t;
123 /* local functions */
124 static void Probe ( aout_instance_t * );
125 static int OpenWaveOut ( aout_instance_t *, uint32_t,
126 int, int, int, int, bool );
127 static int OpenWaveOutPCM( aout_instance_t *, uint32_t,
128 int*, int, int, int, bool );
129 static int PlayWaveOut ( aout_instance_t *, HWAVEOUT, WAVEHDR *,
130 aout_buffer_t *, bool );
132 static void CALLBACK WaveOutCallback ( HWAVEOUT, UINT, DWORD, DWORD, DWORD );
133 static void WaveOutThread( notification_thread_t * );
135 static int VolumeInfos( aout_instance_t *, audio_volume_t * );
136 static int VolumeGet( aout_instance_t *, audio_volume_t * );
137 static int VolumeSet( aout_instance_t *, audio_volume_t );
139 static int WaveOutClearDoneBuffers(aout_sys_t *p_sys);
141 static int ReloadWaveoutDevices( vlc_object_t *, char const *,
142 vlc_value_t, vlc_value_t, void * );
143 static uint32_t findDeviceID(char *);
145 static const char psz_device_name_fmt[] = "%s ($%x,$%x)";
147 static const char *const ppsz_adev[] = { "wavemapper", };
148 static const char *const ppsz_adev_text[] = { N_("Microsoft Soundmapper") };
152 /*****************************************************************************
154 *****************************************************************************/
155 #define FLOAT_TEXT N_("Use float32 output")
156 #define FLOAT_LONGTEXT N_( \
157 "The option allows you to enable or disable the high-quality float32 " \
158 "audio output mode (which is not well supported by some soundcards)." )
159 #define DEVICE_TEXT N_("Select Audio Device")
160 #define DEVICE_LONG N_("Select special Audio device, or let windows "\
161 "decide (default), change needs VLC restart "\
163 #define DEFAULT_AUDIO_DEVICE N_("Default Audio Device")
166 set_shortname( "WaveOut" );
167 set_description( N_("Win32 waveOut extension output") );
168 set_capability( "audio output", 50 );
169 set_category( CAT_AUDIO );
170 set_subcategory( SUBCAT_AUDIO_AOUT );
171 add_bool( "waveout-float32", 1, 0, FLOAT_TEXT, FLOAT_LONGTEXT, true );
173 add_string( "waveout-dev", "wavemapper", NULL,
174 DEVICE_TEXT, DEVICE_LONG, false );
175 change_string_list( ppsz_adev, ppsz_adev_text, ReloadWaveoutDevices );
176 change_need_restart();
177 change_action_add( ReloadWaveoutDevices, N_("Refresh list") );
180 set_callbacks( Open, Close );
183 /*****************************************************************************
184 * aout_sys_t: waveOut audio output method descriptor
185 *****************************************************************************
186 * This structure is part of the audio output thread descriptor.
187 * It describes the waveOut specific properties of an audio device.
188 *****************************************************************************/
191 uint32_t i_wave_device_id; /* ID of selected output device */
193 HWAVEOUT h_waveout; /* handle to waveout instance */
195 WAVEFORMATEXTENSIBLE waveformat; /* audio format */
197 WAVEHDR waveheader[FRAMES_NUM];
199 notification_thread_t *p_notif; /* WaveOutThread id */
201 HANDLE new_buffer_event;
203 // rental from alsa.c to synchronize startup of audiothread
204 int b_playing; /* playing status */
207 int i_repeat_counter;
211 uint8_t *p_silence_buffer; /* buffer we use to play silence */
213 bool b_chan_reorder; /* do we need channel reordering */
214 int pi_chan_table[AOUT_CHAN_MAX];
217 static const uint32_t pi_channels_src[] =
218 { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT,
219 AOUT_CHAN_MIDDLELEFT, AOUT_CHAN_MIDDLERIGHT,
220 AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT,
221 AOUT_CHAN_CENTER, AOUT_CHAN_LFE, 0 };
222 static const uint32_t pi_channels_in[] =
223 { SPEAKER_FRONT_LEFT, SPEAKER_FRONT_RIGHT,
224 SPEAKER_SIDE_LEFT, SPEAKER_SIDE_RIGHT,
225 SPEAKER_BACK_LEFT, SPEAKER_BACK_RIGHT,
226 SPEAKER_FRONT_CENTER, SPEAKER_LOW_FREQUENCY, 0 };
227 static const uint32_t pi_channels_out[] =
228 { SPEAKER_FRONT_LEFT, SPEAKER_FRONT_RIGHT,
229 SPEAKER_FRONT_CENTER, SPEAKER_LOW_FREQUENCY,
230 SPEAKER_BACK_LEFT, SPEAKER_BACK_RIGHT,
231 SPEAKER_SIDE_LEFT, SPEAKER_SIDE_RIGHT, 0 };
233 /*****************************************************************************
234 * Open: open the audio device
235 *****************************************************************************
236 * This function opens and setups Win32 waveOut
237 *****************************************************************************/
238 static int Open( vlc_object_t *p_this )
240 aout_instance_t *p_aout = (aout_instance_t *)p_this;
244 /* Allocate structure */
245 p_aout->output.p_sys = malloc( sizeof( aout_sys_t ) );
247 if( p_aout->output.p_sys == NULL )
249 msg_Err( p_aout, "out of memory" );
253 p_aout->output.pf_play = Play;
254 p_aout->b_die = false;
258 initialize/update Device selection List
260 ReloadWaveoutDevices( p_this, "waveout-dev", val, val, NULL);
264 check for configured audio device!
266 char *psz_waveout_dev = var_CreateGetString( p_aout, "waveout-dev");
268 p_aout->output.p_sys->i_wave_device_id =
269 findDeviceID( psz_waveout_dev );
271 if(p_aout->output.p_sys->i_wave_device_id == WAVE_MAPPER)
273 if(psz_waveout_dev &&
274 stricmp(psz_waveout_dev,"wavemapper"))
276 msg_Warn( p_aout, "configured audio device '%s' not available, "\
277 "use default instead", psz_waveout_dev );
280 free( psz_waveout_dev );
283 WAVEOUTCAPS waveoutcaps;
284 if(waveOutGetDevCaps( p_aout->output.p_sys->i_wave_device_id,
286 sizeof(WAVEOUTCAPS)) == MMSYSERR_NOERROR)
288 /* log debug some infos about driver, to know who to blame
289 if it doesn't work */
290 msg_Dbg( p_aout, "Drivername: %s", waveoutcaps.szPname);
291 msg_Dbg( p_aout, "Driver Version: %d.%d",
292 (waveoutcaps.vDriverVersion>>8)&255,
293 waveoutcaps.vDriverVersion & 255);
294 msg_Dbg( p_aout, "Manufacturer identifier: 0x%x", waveoutcaps.wMid );
295 msg_Dbg( p_aout, "Product identifier: 0x%x", waveoutcaps.wPid );
300 if( var_Type( p_aout, "audio-device" ) == 0 )
305 if( var_Get( p_aout, "audio-device", &val ) < 0 )
307 /* Probe() has failed. */
308 var_Destroy( p_aout, "waveout-device");
309 free( p_aout->output.p_sys );
314 /* Open the device */
315 if( val.i_int == AOUT_VAR_SPDIF )
317 p_aout->output.output.i_format = VLC_FOURCC('s','p','d','i');
319 if( OpenWaveOut( p_aout,
320 p_aout->output.p_sys->i_wave_device_id,
321 VLC_FOURCC('s','p','d','i'),
322 p_aout->output.output.i_physical_channels,
323 aout_FormatNbChannels( &p_aout->output.output ),
324 p_aout->output.output.i_rate, false )
327 msg_Err( p_aout, "cannot open waveout audio device" );
328 free( p_aout->output.p_sys );
332 /* Calculate the frame size in bytes */
333 p_aout->output.i_nb_samples = A52_FRAME_NB;
334 p_aout->output.output.i_bytes_per_frame = AOUT_SPDIF_SIZE;
335 p_aout->output.output.i_frame_length = A52_FRAME_NB;
336 p_aout->output.p_sys->i_buffer_size =
337 p_aout->output.output.i_bytes_per_frame;
339 aout_VolumeNoneInit( p_aout );
345 if( val.i_int == AOUT_VAR_5_1 )
347 p_aout->output.output.i_physical_channels
348 = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
349 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
352 else if( val.i_int == AOUT_VAR_2F2R )
354 p_aout->output.output.i_physical_channels
355 = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
356 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
358 else if( val.i_int == AOUT_VAR_MONO )
360 p_aout->output.output.i_physical_channels = AOUT_CHAN_CENTER;
364 p_aout->output.output.i_physical_channels
365 = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
368 if( OpenWaveOutPCM( p_aout,
369 p_aout->output.p_sys->i_wave_device_id,
370 &p_aout->output.output.i_format,
371 p_aout->output.output.i_physical_channels,
372 aout_FormatNbChannels( &p_aout->output.output ),
373 p_aout->output.output.i_rate, false )
376 msg_Err( p_aout, "cannot open waveout audio device" );
377 free( p_aout->output.p_sys );
381 /* Calculate the frame size in bytes */
382 p_aout->output.i_nb_samples = FRAME_SIZE;
383 aout_FormatPrepare( &p_aout->output.output );
384 p_aout->output.p_sys->i_buffer_size = FRAME_SIZE *
385 p_aout->output.output.i_bytes_per_frame;
387 aout_VolumeSoftInit( p_aout );
389 /* Check for hardware volume support */
390 if( waveOutGetDevCaps( (UINT_PTR)p_aout->output.p_sys->h_waveout,
391 &wocaps, sizeof(wocaps) ) == MMSYSERR_NOERROR &&
392 wocaps.dwSupport & WAVECAPS_VOLUME )
395 if( waveOutGetVolume( p_aout->output.p_sys->h_waveout, &i_dummy )
396 == MMSYSERR_NOERROR )
398 p_aout->output.pf_volume_infos = VolumeInfos;
399 p_aout->output.pf_volume_get = VolumeGet;
400 p_aout->output.pf_volume_set = VolumeSet;
406 waveOutReset( p_aout->output.p_sys->h_waveout );
408 /* Allocate silence buffer */
409 p_aout->output.p_sys->p_silence_buffer =
410 malloc( p_aout->output.p_sys->i_buffer_size );
411 if( p_aout->output.p_sys->p_silence_buffer == NULL )
413 free( p_aout->output.p_sys );
414 msg_Err( p_aout, "out of memory" );
417 p_aout->output.p_sys->i_repeat_counter = 0;
420 /* Zero the buffer. WinCE doesn't have calloc(). */
421 memset( p_aout->output.p_sys->p_silence_buffer, 0,
422 p_aout->output.p_sys->i_buffer_size );
424 /* Now we need to setup our waveOut play notification structure */
425 p_aout->output.p_sys->p_notif =
426 vlc_object_create( p_aout, sizeof(notification_thread_t) );
427 p_aout->output.p_sys->p_notif->p_aout = p_aout;
428 p_aout->output.p_sys->event = CreateEvent( NULL, FALSE, FALSE, NULL );
429 p_aout->output.p_sys->new_buffer_event = CreateEvent( NULL, FALSE, FALSE, NULL );
431 /* define startpoint of playback on first call to play()
432 like alsa does (instead of playing a blank sample) */
433 p_aout->output.p_sys->b_playing = 0;
434 p_aout->output.p_sys->start_date = 0;
437 /* Then launch the notification thread */
438 if( vlc_thread_create( p_aout->output.p_sys->p_notif,
439 "waveOut Notification Thread", WaveOutThread,
440 VLC_THREAD_PRIORITY_OUTPUT, false ) )
442 msg_Err( p_aout, "cannot create WaveOutThread" );
445 /* We need to kick off the playback in order to have the callback properly
447 for( i = 0; i < FRAMES_NUM; i++ )
449 p_aout->output.p_sys->waveheader[i].dwFlags = WHDR_DONE;
450 p_aout->output.p_sys->waveheader[i].dwUser = 0;
456 /*****************************************************************************
457 * Probe: probe the audio device for available formats and channels
458 *****************************************************************************/
459 static void Probe( aout_instance_t * p_aout )
461 vlc_value_t val, text;
463 unsigned int i_physical_channels;
465 var_Create( p_aout, "audio-device", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
466 text.psz_string = _("Audio Device");
467 var_Change( p_aout, "audio-device", VLC_VAR_SETTEXT, &text, NULL );
469 /* Test for 5.1 support */
470 i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
471 AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT |
472 AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE;
473 if( p_aout->output.output.i_physical_channels == i_physical_channels )
475 if( OpenWaveOutPCM( p_aout,
476 p_aout->output.p_sys->i_wave_device_id,
478 i_physical_channels, 6,
479 p_aout->output.output.i_rate, true )
482 val.i_int = AOUT_VAR_5_1;
483 text.psz_string = (char *)N_("5.1");
484 var_Change( p_aout, "audio-device",
485 VLC_VAR_ADDCHOICE, &val, &text );
486 msg_Dbg( p_aout, "device supports 5.1 channels" );
490 /* Test for 2 Front 2 Rear support */
491 i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
492 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
493 if( ( p_aout->output.output.i_physical_channels & i_physical_channels )
494 == i_physical_channels )
496 if( OpenWaveOutPCM( p_aout,
497 p_aout->output.p_sys->i_wave_device_id,
499 i_physical_channels, 4,
500 p_aout->output.output.i_rate, true )
503 val.i_int = AOUT_VAR_2F2R;
504 text.psz_string = (char *)N_("2 Front 2 Rear");
505 var_Change( p_aout, "audio-device",
506 VLC_VAR_ADDCHOICE, &val, &text );
507 msg_Dbg( p_aout, "device supports 4 channels" );
511 /* Test for stereo support */
512 i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
513 if( OpenWaveOutPCM( p_aout,
514 p_aout->output.p_sys->i_wave_device_id,
516 i_physical_channels, 2,
517 p_aout->output.output.i_rate, true )
520 val.i_int = AOUT_VAR_STEREO;
521 text.psz_string = (char *)N_("Stereo");
522 var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text );
523 msg_Dbg( p_aout, "device supports 2 channels" );
526 /* Test for mono support */
527 i_physical_channels = AOUT_CHAN_CENTER;
528 if( OpenWaveOutPCM( p_aout,
529 p_aout->output.p_sys->i_wave_device_id,
531 i_physical_channels, 1,
532 p_aout->output.output.i_rate, true )
535 val.i_int = AOUT_VAR_MONO;
536 text.psz_string = (char *)N_("Mono");
537 var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text );
538 msg_Dbg( p_aout, "device supports 1 channel" );
541 /* Test for SPDIF support */
542 if ( AOUT_FMT_NON_LINEAR( &p_aout->output.output ) )
544 if( OpenWaveOut( p_aout,
545 p_aout->output.p_sys->i_wave_device_id,
546 VLC_FOURCC('s','p','d','i'),
547 p_aout->output.output.i_physical_channels,
548 aout_FormatNbChannels( &p_aout->output.output ),
549 p_aout->output.output.i_rate, true )
552 msg_Dbg( p_aout, "device supports A/52 over S/PDIF" );
553 val.i_int = AOUT_VAR_SPDIF;
554 text.psz_string = (char *)N_("A/52 over S/PDIF");
555 var_Change( p_aout, "audio-device",
556 VLC_VAR_ADDCHOICE, &val, &text );
557 if( config_GetInt( p_aout, "spdif" ) )
558 var_Set( p_aout, "audio-device", val );
562 var_Change( p_aout, "audio-device", VLC_VAR_CHOICESCOUNT, &val, NULL );
565 /* Probe() has failed. */
566 var_Destroy( p_aout, "audio-device" );
570 var_AddCallback( p_aout, "audio-device", aout_ChannelsRestart, NULL );
573 var_Set( p_aout, "intf-change", val );
576 /*****************************************************************************
577 * Play: play a sound buffer
578 *****************************************************************************
579 * This doesn't actually play the buffer. This just stores the buffer so it
580 * can be played by the callback thread.
581 *****************************************************************************/
582 static void Play( aout_instance_t *_p_aout )
584 if( !_p_aout->output.p_sys->b_playing )
586 _p_aout->output.p_sys->b_playing = 1;
588 /* get the playing date of the first aout buffer */
589 _p_aout->output.p_sys->start_date =
590 aout_FifoFirstDate( _p_aout, &_p_aout->output.fifo );
592 msg_Dbg( _p_aout, "Wakeup sleeping output thread.");
594 /* wake up the audio output thread */
595 SetEvent( _p_aout->output.p_sys->event );
597 SetEvent( _p_aout->output.p_sys->new_buffer_event );
601 /*****************************************************************************
602 * Close: close the audio device
603 *****************************************************************************/
604 static void Close( vlc_object_t *p_this )
606 aout_instance_t *p_aout = (aout_instance_t *)p_this;
607 aout_sys_t *p_sys = p_aout->output.p_sys;
609 /* Before calling waveOutClose we must reset the device */
610 vlc_object_kill( p_aout );
612 /* wake up the audio thread, to recognize that p_aout died */
613 SetEvent( p_sys->event );
614 SetEvent( p_sys->new_buffer_event );
616 vlc_thread_join( p_sys->p_notif );
617 vlc_object_release( p_sys->p_notif );
620 kill the real output then - when the feed thread
621 is surely terminated!
622 old code could be too early in case that "feeding"
623 was running on termination
625 at this point now its sure, that there will be no new
626 data send to the driver, and we can cancel the last
629 MMRESULT result = waveOutReset( p_sys->h_waveout );
630 if(result != MMSYSERR_NOERROR)
632 msg_Err( p_aout, "waveOutReset failed 0x%x", result );
634 now we must wait, that all buffers are played
635 because cancel doesn't work in this case...
637 if(result == MMSYSERR_NOTSUPPORTED)
640 clear currently played (done) buffers,
641 if returnvalue > 0 (means some buffer still playing)
642 wait for the driver event callback that one buffer
643 is finished with playing, and check again
644 the timeout of 5000ms is just, an emergency exit
645 of this loop, to avoid deadlock in case of other
646 (currently not known bugs, problems, errors cases?)
649 (WaveOutClearDoneBuffers( p_sys ) > 0)
651 (WaitForSingleObject( p_sys->event, 5000) == WAIT_OBJECT_0)
654 msg_Dbg( p_aout, "Wait for waveout device...");
658 WaveOutClearDoneBuffers( p_sys );
661 /* now we can Close the device */
662 if( waveOutClose( p_sys->h_waveout ) != MMSYSERR_NOERROR )
664 msg_Err( p_aout, "waveOutClose failed" );
668 because so long, the waveout device is playing, the callback
669 could occur and need the events
671 CloseHandle( p_sys->event );
672 CloseHandle( p_sys->new_buffer_event);
674 free( p_sys->p_silence_buffer );
678 /*****************************************************************************
679 * OpenWaveOut: open the waveout sound device
680 ****************************************************************************/
681 static int OpenWaveOut( aout_instance_t *p_aout, uint32_t i_device_id, int i_format,
682 int i_channels, int i_nb_channels, int i_rate,
688 /* Set sound format */
690 #define waveformat p_aout->output.p_sys->waveformat
692 waveformat.dwChannelMask = 0;
693 for( i = 0; i < sizeof(pi_channels_src)/sizeof(uint32_t); i++ )
695 if( i_channels & pi_channels_src[i] )
696 waveformat.dwChannelMask |= pi_channels_in[i];
701 case VLC_FOURCC('s','p','d','i'):
703 /* To prevent channel re-ordering */
704 waveformat.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
705 waveformat.Format.wBitsPerSample = 16;
706 waveformat.Samples.wValidBitsPerSample =
707 waveformat.Format.wBitsPerSample;
708 waveformat.Format.wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF;
709 waveformat.SubFormat = __KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF;
712 case VLC_FOURCC('f','l','3','2'):
713 waveformat.Format.wBitsPerSample = sizeof(float) * 8;
714 waveformat.Samples.wValidBitsPerSample =
715 waveformat.Format.wBitsPerSample;
716 waveformat.Format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
717 waveformat.SubFormat = __KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
720 case VLC_FOURCC('s','1','6','l'):
721 waveformat.Format.wBitsPerSample = 16;
722 waveformat.Samples.wValidBitsPerSample =
723 waveformat.Format.wBitsPerSample;
724 waveformat.Format.wFormatTag = WAVE_FORMAT_PCM;
725 waveformat.SubFormat = __KSDATAFORMAT_SUBTYPE_PCM;
729 waveformat.Format.nChannels = i_nb_channels;
730 waveformat.Format.nSamplesPerSec = i_rate;
731 waveformat.Format.nBlockAlign =
732 waveformat.Format.wBitsPerSample / 8 * i_nb_channels;
733 waveformat.Format.nAvgBytesPerSec =
734 waveformat.Format.nSamplesPerSec * waveformat.Format.nBlockAlign;
736 /* Only use the new WAVE_FORMAT_EXTENSIBLE format for multichannel audio */
737 if( i_nb_channels <= 2 )
739 waveformat.Format.cbSize = 0;
743 waveformat.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
744 waveformat.Format.cbSize =
745 sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
749 msg_Dbg( p_aout, "OpenWaveDevice-ID: %u", i_device_id);
750 msg_Dbg( p_aout,"waveformat.Format.cbSize = %d",
751 waveformat.Format.cbSize);
752 msg_Dbg( p_aout,"waveformat.Format.wFormatTag = %u",
753 waveformat.Format.wFormatTag);
754 msg_Dbg( p_aout,"waveformat.Format.nChannels = %u",
755 waveformat.Format.nChannels);
756 msg_Dbg( p_aout,"waveformat.Format.nSamplesPerSec = %d",
757 (int)waveformat.Format.nSamplesPerSec);
758 msg_Dbg( p_aout,"waveformat.Format.nAvgBytesPerSec = %u",
759 (int)waveformat.Format.nAvgBytesPerSec);
760 msg_Dbg( p_aout,"waveformat.Format.nBlockAlign = %d",
761 waveformat.Format.nBlockAlign);
762 msg_Dbg( p_aout,"waveformat.Format.wBitsPerSample = %d",
763 waveformat.Format.wBitsPerSample);
764 msg_Dbg( p_aout,"waveformat.Samples.wValidBitsPerSample = %d",
765 waveformat.Samples.wValidBitsPerSample);
766 msg_Dbg( p_aout,"waveformat.Samples.wSamplesPerBlock = %d",
767 waveformat.Samples.wSamplesPerBlock);
768 msg_Dbg( p_aout,"waveformat.dwChannelMask = %lu",
769 waveformat.dwChannelMask);
772 /* Open the device */
773 result = waveOutOpen( &p_aout->output.p_sys->h_waveout, i_device_id,
774 (WAVEFORMATEX *)&waveformat,
775 (DWORD_PTR)WaveOutCallback, (DWORD_PTR)p_aout,
776 CALLBACK_FUNCTION | (b_probe?WAVE_FORMAT_QUERY:0) );
777 if( result == WAVERR_BADFORMAT )
779 msg_Warn( p_aout, "waveOutOpen failed WAVERR_BADFORMAT" );
782 if( result == MMSYSERR_ALLOCATED )
784 msg_Warn( p_aout, "waveOutOpen failed WAVERR_ALLOCATED" );
787 if( result != MMSYSERR_NOERROR )
789 msg_Warn( p_aout, "waveOutOpen failed" );
793 p_aout->output.p_sys->b_chan_reorder =
794 aout_CheckChannelReorder( pi_channels_in, pi_channels_out,
795 waveformat.dwChannelMask, i_nb_channels,
796 p_aout->output.p_sys->pi_chan_table );
798 if( p_aout->output.p_sys->b_chan_reorder )
800 msg_Dbg( p_aout, "channel reordering needed" );
809 /*****************************************************************************
810 * OpenWaveOutPCM: open a PCM waveout sound device
811 ****************************************************************************/
812 static int OpenWaveOutPCM( aout_instance_t *p_aout, uint32_t i_device_id, int *i_format,
813 int i_channels, int i_nb_channels, int i_rate,
816 bool b_use_float32 = var_CreateGetBool( p_aout, "waveout-float32");
818 if( !b_use_float32 || OpenWaveOut( p_aout, i_device_id, VLC_FOURCC('f','l','3','2'),
819 i_channels, i_nb_channels, i_rate, b_probe )
822 if ( OpenWaveOut( p_aout, i_device_id, VLC_FOURCC('s','1','6','l'),
823 i_channels, i_nb_channels, i_rate, b_probe )
830 *i_format = VLC_FOURCC('s','1','6','l');
836 *i_format = VLC_FOURCC('f','l','3','2');
841 /*****************************************************************************
842 * PlayWaveOut: play a buffer through the WaveOut device
843 *****************************************************************************/
844 static int PlayWaveOut( aout_instance_t *p_aout, HWAVEOUT h_waveout,
845 WAVEHDR *p_waveheader, aout_buffer_t *p_buffer,
850 /* Prepare the buffer */
851 if( p_buffer != NULL )
853 p_waveheader->lpData = p_buffer->p_buffer;
855 copy the buffer to the silence buffer :) so in case we don't
856 get the next buffer fast enough (I will repeat this one a time
857 for AC3 / DTS and SPDIF this will sound better instead of
862 vlc_memcpy( p_aout->output.p_sys->p_silence_buffer,
864 p_aout->output.p_sys->i_buffer_size );
865 p_aout->output.p_sys->i_repeat_counter = 2;
868 /* Use silence buffer instead */
869 if(p_aout->output.p_sys->i_repeat_counter)
871 p_aout->output.p_sys->i_repeat_counter--;
872 if(!p_aout->output.p_sys->i_repeat_counter)
874 vlc_memset( p_aout->output.p_sys->p_silence_buffer,
875 0x00, p_aout->output.p_sys->i_buffer_size );
878 p_waveheader->lpData = p_aout->output.p_sys->p_silence_buffer;
881 p_waveheader->dwUser = p_buffer ? (DWORD_PTR)p_buffer : (DWORD_PTR)1;
882 p_waveheader->dwBufferLength = p_aout->output.p_sys->i_buffer_size;
883 p_waveheader->dwFlags = 0;
885 result = waveOutPrepareHeader( h_waveout, p_waveheader, sizeof(WAVEHDR) );
886 if( result != MMSYSERR_NOERROR )
888 msg_Err( p_aout, "waveOutPrepareHeader failed" );
892 /* Send the buffer to the waveOut queue */
893 result = waveOutWrite( h_waveout, p_waveheader, sizeof(WAVEHDR) );
894 if( result != MMSYSERR_NOERROR )
896 msg_Err( p_aout, "waveOutWrite failed" );
903 /*****************************************************************************
904 * WaveOutCallback: what to do once WaveOut has played its sound samples
905 *****************************************************************************/
906 static void CALLBACK WaveOutCallback( HWAVEOUT h_waveout, UINT uMsg,
908 DWORD dwParam1, DWORD dwParam2 )
910 aout_instance_t *p_aout = (aout_instance_t *)_p_aout;
911 int i, i_queued_frames = 0;
913 if( uMsg != WOM_DONE ) return;
915 if( p_aout->b_die ) return;
917 /* Find out the current latency */
918 for( i = 0; i < FRAMES_NUM; i++ )
920 /* Check if frame buf is available */
921 if( !(p_aout->output.p_sys->waveheader[i].dwFlags & WHDR_DONE) )
927 /* Don't wake up the thread too much */
928 if( i_queued_frames <= FRAMES_NUM/2 )
929 SetEvent( p_aout->output.p_sys->event );
933 /****************************************************************************
934 * WaveOutClearDoneBuffers: Clear all done marked buffers, and free aout_bufer
935 ****************************************************************************
936 * return value is the number of still playing buffers in the queue
937 ****************************************************************************/
938 static int WaveOutClearDoneBuffers(aout_sys_t *p_sys)
940 WAVEHDR *p_waveheader = p_sys->waveheader;
941 int i_queued_frames = 0;
943 for( int i = 0; i < FRAMES_NUM; i++ )
945 if( (p_waveheader[i].dwFlags & WHDR_DONE) &&
946 p_waveheader[i].dwUser )
948 aout_buffer_t *p_buffer =
949 (aout_buffer_t *)(p_waveheader[i].dwUser);
950 /* Unprepare and free the buffers which has just been played */
951 waveOutUnprepareHeader( p_sys->h_waveout, &p_waveheader[i],
954 if( p_waveheader[i].dwUser != 1 )
955 aout_BufferFree( p_buffer );
957 p_waveheader[i].dwUser = 0;
960 /* Check if frame buf is available */
961 if( !(p_waveheader[i].dwFlags & WHDR_DONE) )
966 return i_queued_frames;
969 /*****************************************************************************
970 * WaveOutThread: this thread will capture play notification events.
971 *****************************************************************************
972 * We use this thread to feed new audio samples to the sound card because
973 * we are not authorized to use waveOutWrite() directly in the waveout
975 *****************************************************************************/
976 static void WaveOutThread( notification_thread_t *p_notif )
978 aout_instance_t *p_aout = p_notif->p_aout;
979 aout_sys_t *p_sys = p_aout->output.p_sys;
980 aout_buffer_t *p_buffer = NULL;
981 WAVEHDR *p_waveheader = p_sys->waveheader;
982 int i, i_queued_frames;
985 uint32_t i_buffer_length = 64;
987 /* We don't want any resampling when using S/PDIF */
988 b_sleek = p_aout->output.output.i_format == VLC_FOURCC('s','p','d','i');
990 // wait for first call to "play()"
991 while( !p_sys->start_date && !p_aout->b_die )
992 WaitForSingleObject( p_sys->event, INFINITE );
996 msg_Dbg( p_aout, "will start to play in %"PRId64" us",
997 (p_sys->start_date - AOUT_PTS_TOLERANCE/4)-mdate());
999 // than wait a short time... before grabbing first frames
1000 mwait( p_sys->start_date - AOUT_PTS_TOLERANCE/4 );
1002 #define waveout_warn(msg) msg_Warn( p_aout, "aout_OutputNextBuffer no buffer "\
1003 "got next_date=%d ms, "\
1004 "%d frames to play, "\
1005 "starving? %d, %s",(int)(next_date/(mtime_t)1000), \
1007 p_aout->output.b_starving, msg);
1008 next_date = mdate();
1010 while( !p_aout->b_die )
1012 /* Cleanup and find out the current latency */
1013 i_queued_frames = WaveOutClearDoneBuffers( p_sys );
1015 if( p_aout->b_die ) return;
1017 /* Try to fill in as many frame buffers as possible */
1018 for( i = 0; i < FRAMES_NUM; i++ )
1020 /* Check if frame buf is available */
1021 if( p_waveheader[i].dwFlags & WHDR_DONE )
1023 // next_date = mdate() + 1000000 * i_queued_frames /
1024 // p_aout->output.output.i_rate * p_aout->output.i_nb_samples;
1026 // the realtime has got our back-site:) to come in sync
1027 if(next_date < mdate())
1028 next_date = mdate();
1031 /* Take into account the latency */
1032 p_buffer = aout_OutputNextBuffer( p_aout,
1039 msg_Dbg( p_aout, "aout_OutputNextBuffer no buffer "\
1040 "got next_date=%d ms, "\
1041 "%d frames to play, "\
1042 "starving? %d",(int)(next_date/(mtime_t)1000),
1044 p_aout->output.b_starving);
1046 if(p_aout->output.b_starving)
1048 // means we are too early to request a new buffer?
1049 waveout_warn("waiting...")
1050 next_date = aout_FifoFirstDate( p_aout, &p_aout->output.fifo );
1051 mwait( next_date - AOUT_PTS_TOLERANCE/4 );
1052 next_date = mdate();
1053 p_buffer = aout_OutputNextBuffer( p_aout,
1060 if( !p_buffer && i_queued_frames )
1062 /* We aren't late so no need to play a blank sample */
1068 mtime_t buffer_length = (p_buffer->end_date
1069 - p_buffer->start_date);
1070 next_date = next_date + buffer_length;
1071 i_buffer_length = buffer_length/1000;
1074 /* Do the channel reordering */
1075 if( p_buffer && p_sys->b_chan_reorder )
1077 aout_ChannelReorder( p_buffer->p_buffer,
1078 p_buffer->i_nb_bytes,
1079 p_sys->waveformat.Format.nChannels,
1080 p_sys->pi_chan_table,
1081 p_sys->waveformat.Format.wBitsPerSample );
1084 PlayWaveOut( p_aout, p_sys->h_waveout,
1085 &p_waveheader[i], p_buffer, b_sleek );
1091 if( p_aout->b_die ) return;
1094 deal with the case that the loop didn't fillup the buffer to the
1095 max - instead of waiting that half the buffer is played before
1096 fillup the waveout buffers, wait only for the next sample buffer
1097 to arrive at the play method...
1099 this will also avoid, that the last buffer is play until the
1100 end, and then trying to get more data, so it will also
1101 work - if the next buffer will arrive some ms before the
1102 last buffer is finished.
1104 if(i_queued_frames < FRAMES_NUM)
1105 WaitForSingleObject( p_sys->new_buffer_event, INFINITE );
1107 WaitForSingleObject( p_sys->event, INFINITE );
1114 static int VolumeInfos( aout_instance_t * p_aout, audio_volume_t * pi_soft )
1116 *pi_soft = AOUT_VOLUME_MAX / 2;
1120 static int VolumeGet( aout_instance_t * p_aout, audio_volume_t * pi_volume )
1122 DWORD i_waveout_vol;
1125 waveOutGetVolume( 0, &i_waveout_vol );
1127 waveOutGetVolume( p_aout->output.p_sys->h_waveout, &i_waveout_vol );
1130 i_waveout_vol &= 0xFFFF;
1131 *pi_volume = p_aout->output.i_volume =
1132 (i_waveout_vol * AOUT_VOLUME_MAX + 0xFFFF /*rounding*/) / 2 / 0xFFFF;
1136 static int VolumeSet( aout_instance_t * p_aout, audio_volume_t i_volume )
1138 unsigned long i_waveout_vol = i_volume * 0xFFFF * 2 / AOUT_VOLUME_MAX;
1139 i_waveout_vol |= (i_waveout_vol << 16);
1142 waveOutSetVolume( 0, i_waveout_vol );
1144 waveOutSetVolume( p_aout->output.p_sys->h_waveout, i_waveout_vol );
1147 p_aout->output.i_volume = i_volume;
1153 reload the configuration drop down list, of the Audio Devices
1155 static int ReloadWaveoutDevices( vlc_object_t *p_this, char const *psz_name,
1156 vlc_value_t newval, vlc_value_t oldval, void *data )
1160 module_config_t *p_item = config_FindConfig( p_this, psz_name );
1161 if( !p_item ) return VLC_SUCCESS;
1163 /* Clear-up the current list */
1164 if( p_item->i_list )
1166 /* Keep the first entry */
1167 for( i = 1; i < p_item->i_list; i++ )
1169 free((char *)(p_item->ppsz_list[i]) );
1170 free((char *)(p_item->ppsz_list_text[i]) );
1172 /* TODO: Remove when no more needed */
1173 p_item->ppsz_list[i] = NULL;
1174 p_item->ppsz_list_text[i] = NULL;
1178 int wave_devices = waveOutGetNumDevs();
1181 (char **)realloc( p_item->ppsz_list,
1182 (wave_devices+2) * sizeof(char *) );
1183 p_item->ppsz_list_text =
1184 (char **)realloc( p_item->ppsz_list_text,
1185 (wave_devices+2) * sizeof(char *) );
1188 char sz_dev_name[MAXPNAMELEN+32];
1190 for(int i=0; i<wave_devices; i++)
1192 if(waveOutGetDevCaps(i, &caps, sizeof(WAVEOUTCAPS))
1193 == MMSYSERR_NOERROR)
1195 sprintf( sz_dev_name, psz_device_name_fmt, caps.szPname,
1199 p_item->ppsz_list[j] = FromLocaleDup( sz_dev_name );
1200 p_item->ppsz_list_text[j] = FromLocaleDup( sz_dev_name );
1206 p_item->ppsz_list[j] = NULL;
1207 p_item->ppsz_list_text[j] = NULL;
1209 /* Signal change to the interface */
1210 p_item->b_dirty = true;
1216 convert devicename to device ID for output
1217 if device not found return WAVE_MAPPER, so let
1218 windows decide which preferred audio device
1221 static uint32_t findDeviceID(char *psz_device_name)
1223 if(!psz_device_name)
1226 uint32_t wave_devices = waveOutGetNumDevs();
1228 char sz_dev_name[MAXPNAMELEN+32];
1229 for(uint32_t i=0; i<wave_devices; i++)
1231 if(waveOutGetDevCaps(i, &caps, sizeof(WAVEOUTCAPS))
1232 == MMSYSERR_NOERROR)
1234 sprintf(sz_dev_name, psz_device_name_fmt, caps.szPname,
1238 char *psz_temp = FromLocaleDup(sz_dev_name);
1240 if( !stricmp(psz_temp, psz_device_name) )
1242 LocaleFree( psz_temp );
1245 LocaleFree( psz_temp );