]> git.sesse.net Git - vlc/blob - modules/audio_output/waveout.c
Remove WinCE
[vlc] / modules / audio_output / waveout.c
1 /*****************************************************************************
2  * waveout.c : Windows waveOut plugin for vlc
3  *****************************************************************************
4  * Copyright (C) 2001-2009 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Gildas Bazin <gbazin@videolan.org>
8  *          AndrĂ© Weber
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32
33 #include <stdio.h>
34 #include <math.h>
35 #include <wchar.h>
36
37 #define UNICODE
38 #include <vlc_common.h>
39 #include <vlc_plugin.h>
40 #include <vlc_aout.h>
41 #include <vlc_aout_intf.h>
42 #include <vlc_charset.h> /* FromWide() */
43 #include <vlc_atomic.h>
44
45 #include "windows_audio_common.h"
46
47 #define FRAME_SIZE 4096              /* The size is in samples, not in bytes */
48
49 /*****************************************************************************
50  * Local prototypes
51  *****************************************************************************/
52 static int  Open         ( vlc_object_t * );
53 static void Close        ( vlc_object_t * );
54 static void Play         ( audio_output_t *, block_t *, mtime_t * );
55
56 /*****************************************************************************
57  * notification_thread_t: waveOut event thread
58  *****************************************************************************/
59 /* local functions */
60 static void Probe        ( audio_output_t * );
61 static int OpenWaveOut   ( audio_output_t *, uint32_t,
62                            int, int, int, int, bool );
63 static int OpenWaveOutPCM( audio_output_t *, uint32_t,
64                            vlc_fourcc_t*, int, int, int, bool );
65 static int PlayWaveOut   ( audio_output_t *, HWAVEOUT, WAVEHDR *,
66                            block_t *, bool );
67
68 static void CALLBACK WaveOutCallback ( HWAVEOUT, UINT, DWORD_PTR, DWORD_PTR, DWORD_PTR );
69 static void* WaveOutThread( void * );
70
71 static int VolumeSet( audio_output_t *, float );
72 static int MuteSet( audio_output_t *, bool );
73
74 static int WaveOutClearDoneBuffers(aout_sys_t *p_sys);
75
76 static int ReloadWaveoutDevices( vlc_object_t *, const char *,
77                                  char ***, char *** );
78 static uint32_t findDeviceID(char *);
79
80 static const wchar_t device_name_fmt[] = L"%ls ($%x,$%x)";
81
82 /*****************************************************************************
83  * aout_sys_t: waveOut audio output method descriptor
84  *****************************************************************************
85  * This structure is part of the audio output thread descriptor.
86  * It describes the waveOut specific properties of an audio device.
87  *****************************************************************************/
88 struct aout_sys_t
89 {
90     aout_packet_t packet;
91     uint32_t i_wave_device_id;               /* ID of selected output device */
92
93     HWAVEOUT h_waveout;                        /* handle to waveout instance */
94
95     WAVEFORMATEXTENSIBLE waveformat;                         /* audio format */
96
97     WAVEHDR waveheader[FRAMES_NUM];
98
99     vlc_thread_t thread;
100     vlc_atomic_t abort;
101     HANDLE event;
102     HANDLE new_buffer_event;
103
104     // rental from alsa.c to synchronize startup of audiothread
105     int b_playing;                                         /* playing status */
106     mtime_t start_date;
107
108     int i_repeat_counter;
109
110     int i_buffer_size;
111
112     uint8_t *p_silence_buffer;              /* buffer we use to play silence */
113
114     union {
115         float volume;
116         float soft_gain;
117     };
118     union {
119         bool mute;
120         bool soft_mute;
121     };
122
123     bool b_chan_reorder;              /* do we need channel reordering */
124     int pi_chan_table[AOUT_CHAN_MAX];
125 };
126
127 #include "volume.h"
128
129 /*****************************************************************************
130  * Module descriptor
131  *****************************************************************************/
132 #define DEVICE_TEXT N_("Select Audio Device")
133 #define DEVICE_LONG N_("Select special Audio device, or let windows "\
134                        "decide (default), change needs VLC restart "\
135                        "to apply.")
136 #define DEFAULT_AUDIO_DEVICE N_("Default Audio Device")
137
138 vlc_module_begin ()
139     set_shortname( "WaveOut" )
140     set_description( N_("Win32 waveOut extension output") )
141     set_capability( "audio output", 50 )
142     set_category( CAT_AUDIO )
143     set_subcategory( SUBCAT_AUDIO_AOUT )
144
145     add_string( "waveout-audio-device", "wavemapper",
146                  DEVICE_TEXT, DEVICE_LONG, false )
147        change_string_cb( ReloadWaveoutDevices )
148     add_sw_gain( )
149
150     add_bool( "waveout-float32", true, FLOAT_TEXT, FLOAT_LONGTEXT, true )
151
152     set_callbacks( Open, Close )
153 vlc_module_end ()
154
155 /*****************************************************************************
156  * Open: open the audio device
157  *****************************************************************************
158  * This function opens and setups Win32 waveOut
159  *****************************************************************************/
160 static int Open( vlc_object_t *p_this )
161 {
162     audio_output_t *p_aout = (audio_output_t *)p_this;
163     vlc_value_t val;
164
165     /* Allocate structure */
166     p_aout->sys = malloc( sizeof( aout_sys_t ) );
167
168     if( p_aout->sys == NULL )
169         return VLC_ENOMEM;
170
171     p_aout->pf_play = Play;
172     p_aout->pf_pause = aout_PacketPause;
173     p_aout->pf_flush = aout_PacketFlush;
174
175     /*
176       check for configured audio device!
177     */
178     char *psz_waveout_dev = var_CreateGetString( p_aout, "waveout-audio-device");
179
180     p_aout->sys->i_wave_device_id =
181          findDeviceID( psz_waveout_dev );
182
183     if(p_aout->sys->i_wave_device_id == WAVE_MAPPER)
184     {
185        if(psz_waveout_dev &&
186           stricmp(psz_waveout_dev,"wavemapper"))
187        {
188            msg_Warn( p_aout, "configured audio device '%s' not available, "\
189                          "use default instead", psz_waveout_dev );
190        }
191     }
192     free( psz_waveout_dev );
193
194
195     WAVEOUTCAPS waveoutcaps;
196     if(waveOutGetDevCaps( p_aout->sys->i_wave_device_id,
197                           &waveoutcaps,
198                           sizeof(WAVEOUTCAPS)) == MMSYSERR_NOERROR)
199     {
200       /* log debug some infos about driver, to know who to blame
201          if it doesn't work */
202         msg_Dbg( p_aout, "Drivername: %ls", waveoutcaps.szPname);
203         msg_Dbg( p_aout, "Driver Version: %d.%d",
204                           (waveoutcaps.vDriverVersion>>8)&255,
205                           waveoutcaps.vDriverVersion & 255);
206         msg_Dbg( p_aout, "Manufacturer identifier: 0x%x", waveoutcaps.wMid );
207         msg_Dbg( p_aout, "Product identifier: 0x%x", waveoutcaps.wPid );
208     }
209
210
211
212     if( var_Type( p_aout, "audio-device" ) == 0 )
213     {
214         Probe( p_aout );
215     }
216
217     if( var_Get( p_aout, "audio-device", &val ) < 0 )
218     {
219         /* Probe() has failed. */
220         var_Destroy( p_aout, "waveout-audio-device");
221         free( p_aout->sys );
222         return VLC_EGENERIC;
223     }
224
225
226     /* Open the device */
227     if( val.i_int == AOUT_VAR_SPDIF )
228     {
229         p_aout->format.i_format = VLC_CODEC_SPDIFL;
230
231         if( OpenWaveOut( p_aout,
232                          p_aout->sys->i_wave_device_id,
233                          VLC_CODEC_SPDIFL,
234                          p_aout->format.i_physical_channels,
235                          aout_FormatNbChannels( &p_aout->format ),
236                          p_aout->format.i_rate, false )
237             != VLC_SUCCESS )
238         {
239             msg_Err( p_aout, "cannot open waveout audio device" );
240             free( p_aout->sys );
241             return VLC_EGENERIC;
242         }
243
244         /* Calculate the frame size in bytes */
245         p_aout->format.i_bytes_per_frame = AOUT_SPDIF_SIZE;
246         p_aout->format.i_frame_length = A52_FRAME_NB;
247         p_aout->sys->i_buffer_size =
248             p_aout->format.i_bytes_per_frame;
249
250         aout_PacketInit( p_aout, &p_aout->sys->packet, A52_FRAME_NB );
251         p_aout->volume_set = NULL;
252         p_aout->mute_set = NULL;
253     }
254     else
255     {
256         WAVEOUTCAPS wocaps;
257
258         switch( val.i_int )
259         {
260         case AOUT_VAR_5_1:
261             p_aout->format.i_physical_channels
262                     = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
263                       | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
264                       | AOUT_CHAN_LFE;
265             break;
266         case AOUT_VAR_2F2R:
267             p_aout->format.i_physical_channels
268                     = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
269                       | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
270             break;
271         case AOUT_VAR_MONO:
272             p_aout->format.i_physical_channels = AOUT_CHAN_CENTER;
273             break;
274         default:
275             p_aout->format.i_physical_channels
276                     = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
277         }
278
279         if( OpenWaveOutPCM( p_aout,
280                             p_aout->sys->i_wave_device_id,
281                             &p_aout->format.i_format,
282                             p_aout->format.i_physical_channels,
283                             aout_FormatNbChannels( &p_aout->format ),
284                             p_aout->format.i_rate, false )
285             != VLC_SUCCESS )
286         {
287             msg_Err( p_aout, "cannot open waveout audio device" );
288             free( p_aout->sys );
289             return VLC_EGENERIC;
290         }
291
292         /* Calculate the frame size in bytes */
293         aout_FormatPrepare( &p_aout->format );
294         p_aout->sys->i_buffer_size = FRAME_SIZE *
295             p_aout->format.i_bytes_per_frame;
296
297         aout_PacketInit( p_aout, &p_aout->sys->packet, FRAME_SIZE );
298
299         /* Check for hardware volume support */
300         if( waveOutGetDevCaps( (UINT_PTR)p_aout->sys->h_waveout,
301                                &wocaps, sizeof(wocaps) ) == MMSYSERR_NOERROR
302          && (wocaps.dwSupport & WAVECAPS_VOLUME) )
303         {
304             p_aout->volume_set = VolumeSet;
305             p_aout->mute_set = MuteSet;
306             p_aout->sys->volume = 0xffff.fp0;
307             p_aout->sys->mute = false;
308         }
309         else
310             aout_SoftVolumeInit( p_aout );
311     }
312
313     waveOutReset( p_aout->sys->h_waveout );
314
315     /* Allocate silence buffer */
316     p_aout->sys->p_silence_buffer =
317         malloc( p_aout->sys->i_buffer_size );
318     if( p_aout->sys->p_silence_buffer == NULL )
319     {
320         aout_PacketDestroy( p_aout );
321         free( p_aout->sys );
322         return VLC_ENOMEM;
323     }
324     p_aout->sys->i_repeat_counter = 0;
325
326
327     /* Zero the buffer. WinCE doesn't have calloc(). */
328     memset( p_aout->sys->p_silence_buffer, 0,
329             p_aout->sys->i_buffer_size );
330
331     /* Now we need to setup our waveOut play notification structure */
332     p_aout->sys->event = CreateEvent( NULL, FALSE, FALSE, NULL );
333     p_aout->sys->new_buffer_event = CreateEvent( NULL, FALSE, FALSE, NULL );
334
335     /* define startpoint of playback on first call to play()
336       like alsa does (instead of playing a blank sample) */
337     p_aout->sys->b_playing = 0;
338     p_aout->sys->start_date = 0;
339
340
341     /* Then launch the notification thread */
342     vlc_atomic_set( &p_aout->sys->abort, 0);
343     if( vlc_clone( &p_aout->sys->thread,
344                    WaveOutThread, p_aout, VLC_THREAD_PRIORITY_OUTPUT ) )
345     {
346         msg_Err( p_aout, "cannot create WaveOutThread" );
347     }
348
349     /* We need to kick off the playback in order to have the callback properly
350      * working */
351     for( int i = 0; i < FRAMES_NUM; i++ )
352     {
353         p_aout->sys->waveheader[i].dwFlags = WHDR_DONE;
354         p_aout->sys->waveheader[i].dwUser = 0;
355     }
356
357     return VLC_SUCCESS;
358 }
359
360 /*****************************************************************************
361  * Probe: probe the audio device for available formats and channels
362  *****************************************************************************/
363 static void Probe( audio_output_t * p_aout )
364 {
365     vlc_value_t val, text;
366     vlc_fourcc_t i_format;
367     unsigned int i_physical_channels;
368
369     var_Create( p_aout, "audio-device", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
370     text.psz_string = _("Audio Device");
371     var_Change( p_aout, "audio-device", VLC_VAR_SETTEXT, &text, NULL );
372
373     /* Test for 5.1 support */
374     i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
375                           AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT |
376                           AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE;
377     if( p_aout->format.i_physical_channels == i_physical_channels )
378     {
379         if( OpenWaveOutPCM( p_aout,
380                             p_aout->sys->i_wave_device_id,
381                             &i_format,
382                             i_physical_channels, 6,
383                             p_aout->format.i_rate, true )
384             == VLC_SUCCESS )
385         {
386             val.i_int = AOUT_VAR_5_1;
387             text.psz_string = (char *)_("5.1");
388             var_Change( p_aout, "audio-device",
389                         VLC_VAR_ADDCHOICE, &val, &text );
390             msg_Dbg( p_aout, "device supports 5.1 channels" );
391         }
392     }
393
394     /* Test for 2 Front 2 Rear support */
395     i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
396                           AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
397     if( ( p_aout->format.i_physical_channels & i_physical_channels )
398         == i_physical_channels )
399     {
400         if( OpenWaveOutPCM( p_aout,
401                             p_aout->sys->i_wave_device_id,
402                             &i_format,
403                             i_physical_channels, 4,
404                             p_aout->format.i_rate, true )
405             == VLC_SUCCESS )
406         {
407             val.i_int = AOUT_VAR_2F2R;
408             text.psz_string = (char *)_("2 Front 2 Rear");
409             var_Change( p_aout, "audio-device",
410                         VLC_VAR_ADDCHOICE, &val, &text );
411             msg_Dbg( p_aout, "device supports 4 channels" );
412         }
413     }
414
415     /* Test for stereo support */
416     i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
417     if( OpenWaveOutPCM( p_aout,
418                         p_aout->sys->i_wave_device_id,
419                         &i_format,
420                         i_physical_channels, 2,
421                         p_aout->format.i_rate, true )
422         == VLC_SUCCESS )
423     {
424         val.i_int = AOUT_VAR_STEREO;
425         text.psz_string = (char *)_("Stereo");
426         var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text );
427         msg_Dbg( p_aout, "device supports 2 channels" );
428     }
429
430     /* Test for mono support */
431     i_physical_channels = AOUT_CHAN_CENTER;
432     if( OpenWaveOutPCM( p_aout,
433                         p_aout->sys->i_wave_device_id,
434                         &i_format,
435                         i_physical_channels, 1,
436                         p_aout->format.i_rate, true )
437         == VLC_SUCCESS )
438     {
439         val.i_int = AOUT_VAR_MONO;
440         text.psz_string = (char *)_("Mono");
441         var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text );
442         msg_Dbg( p_aout, "device supports 1 channel" );
443     }
444
445     /* Test for SPDIF support */
446     if ( AOUT_FMT_SPDIF( &p_aout->format ) )
447     {
448         if( OpenWaveOut( p_aout,
449                          p_aout->sys->i_wave_device_id,
450                          VLC_CODEC_SPDIFL,
451                          p_aout->format.i_physical_channels,
452                          aout_FormatNbChannels( &p_aout->format ),
453                          p_aout->format.i_rate, true )
454             == VLC_SUCCESS )
455         {
456             msg_Dbg( p_aout, "device supports A/52 over S/PDIF" );
457             val.i_int = AOUT_VAR_SPDIF;
458             text.psz_string = (char *)_("A/52 over S/PDIF");
459             var_Change( p_aout, "audio-device",
460                         VLC_VAR_ADDCHOICE, &val, &text );
461             if( var_InheritBool( p_aout, "spdif" ) )
462                 var_Set( p_aout, "audio-device", val );
463         }
464     }
465
466     var_Change( p_aout, "audio-device", VLC_VAR_CHOICESCOUNT, &val, NULL );
467     if( val.i_int <= 0 )
468     {
469         /* Probe() has failed. */
470         var_Destroy( p_aout, "audio-device" );
471         return;
472     }
473
474     var_AddCallback( p_aout, "audio-device", aout_ChannelsRestart, NULL );
475 }
476
477 /*****************************************************************************
478  * Play: play a sound buffer
479  *****************************************************************************
480  * This doesn't actually play the buffer. This just stores the buffer so it
481  * can be played by the callback thread.
482  *****************************************************************************/
483 static void Play( audio_output_t *_p_aout, block_t *block,
484                   mtime_t *restrict drift )
485 {
486     if( !_p_aout->sys->b_playing )
487     {
488         _p_aout->sys->b_playing = 1;
489
490         /* get the playing date of the first aout buffer */
491         _p_aout->sys->start_date = block->i_pts;
492
493         msg_Dbg( _p_aout, "Wakeup sleeping output thread.");
494
495         /* wake up the audio output thread */
496         SetEvent( _p_aout->sys->event );
497     } else {
498         SetEvent( _p_aout->sys->new_buffer_event );
499     }
500
501     aout_PacketPlay( _p_aout, block, drift );
502 }
503
504 /*****************************************************************************
505  * Close: close the audio device
506  *****************************************************************************/
507 static void Close( vlc_object_t *p_this )
508 {
509     audio_output_t *p_aout = (audio_output_t *)p_this;
510     aout_sys_t *p_sys = p_aout->sys;
511
512     /* Before calling waveOutClose we must reset the device */
513     vlc_atomic_set( &p_sys->abort, 1);
514
515     /* wake up the audio thread, to recognize that p_aout died */
516     SetEvent( p_sys->event );
517     SetEvent( p_sys->new_buffer_event );
518
519     vlc_join( p_sys->thread, NULL );
520
521     /*
522       kill the real output then - when the feed thread
523       is surely terminated!
524       old code could be too early in case that "feeding"
525       was running on termination
526
527       at this point now its sure, that there will be no new
528       data send to the driver, and we can cancel the last
529       running playbuffers
530     */
531     MMRESULT result = waveOutReset( p_sys->h_waveout );
532     if(result != MMSYSERR_NOERROR)
533     {
534        msg_Err( p_aout, "waveOutReset failed 0x%x", result );
535        /*
536         now we must wait, that all buffers are played
537         because cancel doesn't work in this case...
538        */
539        if(result == MMSYSERR_NOTSUPPORTED)
540        {
541            /*
542              clear currently played (done) buffers,
543              if returnvalue > 0 (means some buffer still playing)
544              wait for the driver event callback that one buffer
545              is finished with playing, and check again
546              the timeout of 5000ms is just, an emergency exit
547              of this loop, to avoid deadlock in case of other
548              (currently not known bugs, problems, errors cases?)
549            */
550            while(
551                  (WaveOutClearDoneBuffers( p_sys ) > 0)
552                  &&
553                  (WaitForSingleObject( p_sys->event, 5000) == WAIT_OBJECT_0)
554                 )
555            {
556                  msg_Dbg( p_aout, "Wait for waveout device...");
557            }
558        }
559     } else {
560         WaveOutClearDoneBuffers( p_sys );
561     }
562
563     /* now we can Close the device */
564     if( waveOutClose( p_sys->h_waveout ) != MMSYSERR_NOERROR )
565     {
566         msg_Err( p_aout, "waveOutClose failed" );
567     }
568
569     /*
570       because so long, the waveout device is playing, the callback
571       could occur and need the events
572     */
573     CloseHandle( p_sys->event );
574     CloseHandle( p_sys->new_buffer_event);
575
576     free( p_sys->p_silence_buffer );
577     aout_PacketDestroy( p_aout );
578     free( p_sys );
579 }
580
581 /*****************************************************************************
582  * OpenWaveOut: open the waveout sound device
583  ****************************************************************************/
584 static int OpenWaveOut( audio_output_t *p_aout, uint32_t i_device_id, int i_format,
585                         int i_channels, int i_nb_channels, int i_rate,
586                         bool b_probe )
587 {
588     MMRESULT result;
589
590     /* Set sound format */
591
592 #define waveformat p_aout->sys->waveformat
593
594     waveformat.dwChannelMask = 0;
595     for( unsigned i = 0; pi_vlc_chan_order_wg4[i]; i++ )
596         if( i_channels & pi_vlc_chan_order_wg4[i] )
597             waveformat.dwChannelMask |= pi_channels_in[i];
598
599     switch( i_format )
600     {
601     case VLC_CODEC_SPDIFL:
602         i_nb_channels = 2;
603         /* To prevent channel re-ordering */
604         waveformat.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
605         waveformat.Format.wBitsPerSample = 16;
606         waveformat.Samples.wValidBitsPerSample =
607             waveformat.Format.wBitsPerSample;
608         waveformat.Format.wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF;
609         waveformat.SubFormat = __KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF;
610         break;
611
612     case VLC_CODEC_FL32:
613         waveformat.Format.wBitsPerSample = sizeof(float) * 8;
614         waveformat.Samples.wValidBitsPerSample =
615             waveformat.Format.wBitsPerSample;
616         waveformat.Format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
617         waveformat.SubFormat = __KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
618         break;
619
620     case VLC_CODEC_S16L:
621         waveformat.Format.wBitsPerSample = 16;
622         waveformat.Samples.wValidBitsPerSample =
623             waveformat.Format.wBitsPerSample;
624         waveformat.Format.wFormatTag = WAVE_FORMAT_PCM;
625         waveformat.SubFormat = __KSDATAFORMAT_SUBTYPE_PCM;
626         break;
627     }
628
629     waveformat.Format.nChannels = i_nb_channels;
630     waveformat.Format.nSamplesPerSec = i_rate;
631     waveformat.Format.nBlockAlign =
632         waveformat.Format.wBitsPerSample / 8 * i_nb_channels;
633     waveformat.Format.nAvgBytesPerSec =
634         waveformat.Format.nSamplesPerSec * waveformat.Format.nBlockAlign;
635
636     /* Only use the new WAVE_FORMAT_EXTENSIBLE format for multichannel audio */
637     if( i_nb_channels <= 2 )
638     {
639         waveformat.Format.cbSize = 0;
640     }
641     else
642     {
643         waveformat.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
644         waveformat.Format.cbSize =
645             sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
646     }
647
648     if(!b_probe) {
649         msg_Dbg( p_aout, "OpenWaveDevice-ID: %u", i_device_id);
650         msg_Dbg( p_aout,"waveformat.Format.cbSize          = %d",
651                  waveformat.Format.cbSize);
652         msg_Dbg( p_aout,"waveformat.Format.wFormatTag      = %u",
653                  waveformat.Format.wFormatTag);
654         msg_Dbg( p_aout,"waveformat.Format.nChannels       = %u",
655                  waveformat.Format.nChannels);
656         msg_Dbg( p_aout,"waveformat.Format.nSamplesPerSec  = %d",
657                  (int)waveformat.Format.nSamplesPerSec);
658         msg_Dbg( p_aout,"waveformat.Format.nAvgBytesPerSec = %u",
659                  (int)waveformat.Format.nAvgBytesPerSec);
660         msg_Dbg( p_aout,"waveformat.Format.nBlockAlign     = %d",
661                  waveformat.Format.nBlockAlign);
662         msg_Dbg( p_aout,"waveformat.Format.wBitsPerSample  = %d",
663                  waveformat.Format.wBitsPerSample);
664         msg_Dbg( p_aout,"waveformat.Samples.wValidBitsPerSample = %d",
665                  waveformat.Samples.wValidBitsPerSample);
666         msg_Dbg( p_aout,"waveformat.Samples.wSamplesPerBlock = %d",
667                  waveformat.Samples.wSamplesPerBlock);
668         msg_Dbg( p_aout,"waveformat.dwChannelMask          = %lu",
669                  waveformat.dwChannelMask);
670     }
671
672     /* Open the device */
673     result = waveOutOpen( &p_aout->sys->h_waveout, i_device_id,
674                           (WAVEFORMATEX *)&waveformat,
675                           (DWORD_PTR)WaveOutCallback, (DWORD_PTR)p_aout,
676                           CALLBACK_FUNCTION | (b_probe?WAVE_FORMAT_QUERY:0) );
677     if( result == WAVERR_BADFORMAT )
678     {
679         msg_Warn( p_aout, "waveOutOpen failed WAVERR_BADFORMAT" );
680         return VLC_EGENERIC;
681     }
682     if( result == MMSYSERR_ALLOCATED )
683     {
684         msg_Warn( p_aout, "waveOutOpen failed WAVERR_ALLOCATED" );
685         return VLC_EGENERIC;
686     }
687     if( result != MMSYSERR_NOERROR )
688     {
689         msg_Warn( p_aout, "waveOutOpen failed" );
690         return VLC_EGENERIC;
691     }
692
693     p_aout->sys->b_chan_reorder =
694         aout_CheckChannelReorder( pi_channels_in, pi_channels_out,
695                                   waveformat.dwChannelMask, i_nb_channels,
696                                   p_aout->sys->pi_chan_table );
697
698     if( p_aout->sys->b_chan_reorder )
699     {
700         msg_Dbg( p_aout, "channel reordering needed" );
701     }
702
703     return VLC_SUCCESS;
704
705 #undef waveformat
706
707 }
708
709 /*****************************************************************************
710  * OpenWaveOutPCM: open a PCM waveout sound device
711  ****************************************************************************/
712 static int OpenWaveOutPCM( audio_output_t *p_aout, uint32_t i_device_id,
713                            vlc_fourcc_t *i_format,
714                            int i_channels, int i_nb_channels, int i_rate,
715                            bool b_probe )
716 {
717     bool b_use_float32 = var_CreateGetBool( p_aout, "waveout-float32");
718
719     if( !b_use_float32 || OpenWaveOut( p_aout, i_device_id, VLC_CODEC_FL32,
720                                    i_channels, i_nb_channels, i_rate, b_probe )
721         != VLC_SUCCESS )
722     {
723         if ( OpenWaveOut( p_aout, i_device_id, VLC_CODEC_S16L,
724                           i_channels, i_nb_channels, i_rate, b_probe )
725              != VLC_SUCCESS )
726         {
727             return VLC_EGENERIC;
728         }
729         else
730         {
731             *i_format = VLC_CODEC_S16L;
732             return VLC_SUCCESS;
733         }
734     }
735     else
736     {
737         *i_format = VLC_CODEC_FL32;
738         return VLC_SUCCESS;
739     }
740 }
741
742 /*****************************************************************************
743  * PlayWaveOut: play a buffer through the WaveOut device
744  *****************************************************************************/
745 static int PlayWaveOut( audio_output_t *p_aout, HWAVEOUT h_waveout,
746                         WAVEHDR *p_waveheader, block_t *p_buffer, bool b_spdif)
747 {
748     MMRESULT result;
749
750     /* Prepare the buffer */
751     if( p_buffer != NULL )
752     {
753         p_waveheader->lpData = (LPSTR)p_buffer->p_buffer;
754         /*
755           copy the buffer to the silence buffer :) so in case we don't
756           get the next buffer fast enough (I will repeat this one a time
757           for AC3 / DTS and SPDIF this will sound better instead of
758           a hickup)
759         */
760         if(b_spdif)
761         {
762            memcpy( p_aout->sys->p_silence_buffer,
763                        p_buffer->p_buffer,
764                        p_aout->sys->i_buffer_size );
765            p_aout->sys->i_repeat_counter = 2;
766         }
767     } else {
768         /* Use silence buffer instead */
769         if(p_aout->sys->i_repeat_counter)
770         {
771            p_aout->sys->i_repeat_counter--;
772            if(!p_aout->sys->i_repeat_counter)
773            {
774                memset( p_aout->sys->p_silence_buffer,
775                            0x00, p_aout->sys->i_buffer_size );
776            }
777         }
778         p_waveheader->lpData = (LPSTR)p_aout->sys->p_silence_buffer;
779     }
780
781     p_waveheader->dwUser = p_buffer ? (DWORD_PTR)p_buffer : (DWORD_PTR)1;
782     p_waveheader->dwBufferLength = p_aout->sys->i_buffer_size;
783     p_waveheader->dwFlags = 0;
784
785     result = waveOutPrepareHeader( h_waveout, p_waveheader, sizeof(WAVEHDR) );
786     if( result != MMSYSERR_NOERROR )
787     {
788         msg_Err( p_aout, "waveOutPrepareHeader failed" );
789         return VLC_EGENERIC;
790     }
791
792     /* Send the buffer to the waveOut queue */
793     result = waveOutWrite( h_waveout, p_waveheader, sizeof(WAVEHDR) );
794     if( result != MMSYSERR_NOERROR )
795     {
796         msg_Err( p_aout, "waveOutWrite failed" );
797         return VLC_EGENERIC;
798     }
799
800     return VLC_SUCCESS;
801 }
802
803 /*****************************************************************************
804  * WaveOutCallback: what to do once WaveOut has played its sound samples
805  *****************************************************************************/
806 static void CALLBACK WaveOutCallback( HWAVEOUT h_waveout, UINT uMsg,
807                                       DWORD_PTR _p_aout,
808                                       DWORD_PTR dwParam1, DWORD_PTR dwParam2 )
809 {
810     (void)h_waveout;    (void)dwParam1;    (void)dwParam2;
811     audio_output_t *p_aout = (audio_output_t *)_p_aout;
812     int i_queued_frames = 0;
813
814     if( uMsg != WOM_DONE ) return;
815
816     if( vlc_atomic_get(&p_aout->sys->abort) ) return;
817
818     /* Find out the current latency */
819     for( int i = 0; i < FRAMES_NUM; i++ )
820     {
821         /* Check if frame buf is available */
822         if( !(p_aout->sys->waveheader[i].dwFlags & WHDR_DONE) )
823         {
824             i_queued_frames++;
825         }
826     }
827
828     /* Don't wake up the thread too much */
829     if( i_queued_frames <= FRAMES_NUM/2 )
830         SetEvent( p_aout->sys->event );
831 }
832
833
834 /****************************************************************************
835  * WaveOutClearDoneBuffers: Clear all done marked buffers, and free buffer
836  ****************************************************************************
837  * return value is the number of still playing buffers in the queue
838  ****************************************************************************/
839 static int WaveOutClearDoneBuffers(aout_sys_t *p_sys)
840 {
841     WAVEHDR *p_waveheader = p_sys->waveheader;
842     int i_queued_frames = 0;
843
844     for( int i = 0; i < FRAMES_NUM; i++ )
845     {
846         if( (p_waveheader[i].dwFlags & WHDR_DONE) &&
847             p_waveheader[i].dwUser )
848         {
849             block_t *p_buffer =
850                     (block_t *)(p_waveheader[i].dwUser);
851             /* Unprepare and free the buffers which has just been played */
852             waveOutUnprepareHeader( p_sys->h_waveout, &p_waveheader[i],
853                                     sizeof(WAVEHDR) );
854
855             if( p_waveheader[i].dwUser != 1 )
856                 block_Release( p_buffer );
857
858             p_waveheader[i].dwUser = 0;
859         }
860
861         /* Check if frame buf is available */
862         if( !(p_waveheader[i].dwFlags & WHDR_DONE) )
863         {
864             i_queued_frames++;
865         }
866     }
867     return i_queued_frames;
868 }
869
870 /*****************************************************************************
871  * WaveOutThread: this thread will capture play notification events.
872  *****************************************************************************
873  * We use this thread to feed new audio samples to the sound card because
874  * we are not authorized to use waveOutWrite() directly in the waveout
875  * callback.
876  *****************************************************************************/
877 static void* WaveOutThread( void *data )
878 {
879     audio_output_t *p_aout = data;
880     aout_sys_t *p_sys = p_aout->sys;
881     block_t *p_buffer = NULL;
882     WAVEHDR *p_waveheader = p_sys->waveheader;
883     int i, i_queued_frames;
884     bool b_sleek;
885     mtime_t next_date;
886     int canc = vlc_savecancel ();
887
888     /* We don't want any resampling when using S/PDIF */
889     b_sleek = p_aout->format.i_format == VLC_CODEC_SPDIFL;
890
891     // wait for first call to "play()"
892     while( !p_sys->start_date && !vlc_atomic_get(&p_aout->sys->abort) )
893            WaitForSingleObject( p_sys->event, INFINITE );
894     if( vlc_atomic_get(&p_aout->sys->abort) )
895         return NULL;
896
897     msg_Dbg( p_aout, "will start to play in %"PRId64" us",
898              (p_sys->start_date - AOUT_MAX_PTS_ADVANCE/4)-mdate());
899
900     // than wait a short time... before grabbing first frames
901     mwait( p_sys->start_date - AOUT_MAX_PTS_ADVANCE/4 );
902
903 #define waveout_warn(msg) msg_Warn( p_aout, "aout_PacketNext no buffer "\
904                            "got next_date=%d ms, "\
905                            "%d frames to play, %s",\
906                            (int)(next_date/(mtime_t)1000), \
907                            i_queued_frames, msg);
908     next_date = mdate();
909
910     while( !vlc_atomic_get(&p_aout->sys->abort) )
911     {
912         /* Cleanup and find out the current latency */
913         i_queued_frames = WaveOutClearDoneBuffers( p_sys );
914
915         if( vlc_atomic_get(&p_aout->sys->abort) ) return NULL;
916
917         /* Try to fill in as many frame buffers as possible */
918         for( i = 0; i < FRAMES_NUM; i++ )
919         {
920             /* Check if frame buf is available */
921             if( p_waveheader[i].dwFlags & WHDR_DONE )
922             {
923                 // next_date = mdate() + 1000000 * i_queued_frames /
924                 //  p_aout->format.i_rate * p_aout->i_nb_samples;
925
926                 // the realtime has got our back-site:) to come in sync
927                 if(next_date < mdate())
928                    next_date = mdate();
929
930
931                 /* Take into account the latency */
932                 p_buffer = aout_PacketNext( p_aout, next_date );
933                 if(!p_buffer)
934                 {
935 #if 0
936                     msg_Dbg( p_aout, "aout_PacketNext no buffer got "
937                              "next_date=%"PRId64" ms, %d frames to play",
938                              next_date/1000, i_queued_frames);
939 #endif
940                     // means we are too early to request a new buffer?
941                     waveout_warn("waiting...")
942                     mwait( next_date - AOUT_MAX_PTS_ADVANCE/4 );
943                     next_date = mdate();
944                     p_buffer = aout_PacketNext( p_aout, next_date );
945                 }
946
947                 if( !p_buffer && i_queued_frames )
948                 {
949                     /* We aren't late so no need to play a blank sample */
950                     break;
951                 }
952
953                 if( p_buffer )
954                 {
955                     mtime_t buffer_length = p_buffer->i_length;
956                     next_date = next_date + buffer_length;
957                 }
958
959                 /* Do the channel reordering */
960                 if( p_buffer && p_sys->b_chan_reorder )
961                 {
962                     aout_ChannelReorder( p_buffer->p_buffer,
963                         p_buffer->i_buffer,
964                         p_sys->waveformat.Format.nChannels,
965                         p_sys->pi_chan_table,
966                         p_sys->waveformat.Format.wBitsPerSample );
967                 }
968
969                 PlayWaveOut( p_aout, p_sys->h_waveout,
970                              &p_waveheader[i], p_buffer, b_sleek );
971
972                 i_queued_frames++;
973             }
974         }
975
976         if( vlc_atomic_get(&p_aout->sys->abort) ) return NULL;
977
978         /*
979           deal with the case that the loop didn't fillup the buffer to the
980           max - instead of waiting that half the buffer is played before
981           fillup the waveout buffers, wait only for the next sample buffer
982           to arrive at the play method...
983
984           this will also avoid, that the last buffer is play until the
985           end, and then trying to get more data, so it will also
986           work - if the next buffer will arrive some ms before the
987           last buffer is finished.
988         */
989         if(i_queued_frames < FRAMES_NUM)
990            WaitForSingleObject( p_sys->new_buffer_event, INFINITE );
991         else
992            WaitForSingleObject( p_sys->event, INFINITE );
993
994     }
995
996 #undef waveout_warn
997     vlc_restorecancel (canc);
998     return NULL;
999 }
1000
1001 static int VolumeSet( audio_output_t *aout, float volume )
1002 {
1003     aout_sys_t *sys = aout->sys;
1004     const HWAVEOUT hwo = sys->h_waveout;
1005     const float full = 0xffff.fp0;
1006
1007     volume *= full;
1008     if( volume >= full )
1009         return -1;
1010
1011     sys->volume = volume;
1012     if( sys->mute )
1013         return 0;
1014
1015     uint16_t vol = lroundf(volume);
1016     waveOutSetVolume( hwo, vol | (vol << 16) );
1017     return 0;
1018 }
1019
1020 static int MuteSet( audio_output_t * p_aout, bool mute )
1021 {
1022     aout_sys_t *sys = p_aout->sys;
1023     const HWAVEOUT hwo = sys->h_waveout;
1024     uint16_t vol = mute ? 0 : lroundf(sys->volume);
1025
1026     sys->mute = mute;
1027     waveOutSetVolume( hwo, vol | (vol << 16) );
1028     return 0;
1029 }
1030
1031 /*
1032   reload the configuration drop down list, of the Audio Devices
1033 */
1034 static int ReloadWaveoutDevices( vlc_object_t *p_this, char const *psz_name,
1035                                  char ***values, char ***descs )
1036 {
1037     int n = 0, nb_devices = waveOutGetNumDevs();
1038
1039     VLC_UNUSED( psz_name );
1040
1041     *values = xmalloc( (nb_devices + 1) * sizeof(char *) );
1042     *descs = xmalloc( (nb_devices + 1) * sizeof(char *) );
1043
1044     (*values)[n] = strdup( "wavemapper" );
1045     (*descs)[n] = strdup( _("Microsoft Soundmapper") );
1046     n++;
1047
1048     for(int i = 0; i < nb_devices; i++)
1049     {
1050         WAVEOUTCAPS caps;
1051         wchar_t dev_name[MAXPNAMELEN+32];
1052
1053         if(waveOutGetDevCaps(i, &caps, sizeof(WAVEOUTCAPS))
1054                                                            != MMSYSERR_NOERROR)
1055             continue;
1056
1057         _snwprintf(dev_name, MAXPNAMELEN + 32, device_name_fmt,
1058                    caps.szPname, caps.wMid, caps.wPid);
1059         (*values)[n] = FromWide( dev_name );
1060         (*descs)[n] = strdup( (*values)[n] );
1061         n++;
1062     }
1063
1064     return n;
1065 }
1066
1067 /*
1068   convert devicename to device ID for output
1069   if device not found return WAVE_MAPPER, so let
1070   windows decide which preferred audio device
1071   should be used.
1072 */
1073 static uint32_t findDeviceID(char *psz_device_name)
1074 {
1075     if( !psz_device_name )
1076        return WAVE_MAPPER;
1077
1078     uint32_t wave_devices = waveOutGetNumDevs();
1079
1080     for( uint32_t i = 0; i < wave_devices; i++ )
1081     {
1082         WAVEOUTCAPS caps;
1083         wchar_t dev_name[MAXPNAMELEN+32];
1084
1085         if( waveOutGetDevCaps( i, &caps, sizeof(WAVEOUTCAPS) )
1086                                                           != MMSYSERR_NOERROR )
1087             continue;
1088
1089         _snwprintf( dev_name, MAXPNAMELEN + 32, device_name_fmt,
1090                   caps.szPname, caps.wMid, caps.wPid );
1091         char *u8 = FromWide(dev_name);
1092         if( !stricmp(u8, psz_device_name) )
1093         {
1094             free( u8 );
1095             return i;
1096         }
1097         free( u8 );
1098     }
1099
1100     return WAVE_MAPPER;
1101 }