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