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