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