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