]> git.sesse.net Git - vlc/blob - modules/audio_output/waveout.c
RAM: deactivate start-time in rtsp streams
[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_charset.h>                        /* FromLocaleDup, LocaleFree */
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 VolumeSet( aout_instance_t *, audio_volume_t, bool );
72
73 static int WaveOutClearDoneBuffers(aout_sys_t *p_sys);
74
75 static int ReloadWaveoutDevices( vlc_object_t *, char const *,
76                                 vlc_value_t, vlc_value_t, void * );
77 static uint32_t findDeviceID(char *);
78
79 static const char psz_device_name_fmt[] = "%s ($%x,$%x)";
80
81 static const char *const ppsz_adev[] = { "wavemapper", };
82 static const char *const ppsz_adev_text[] = { N_("Microsoft Soundmapper") };
83
84
85 /*****************************************************************************
86  * Module descriptor
87  *****************************************************************************/
88 #define DEVICE_TEXT N_("Select Audio Device")
89 #define DEVICE_LONG N_("Select special Audio device, or let windows "\
90                        "decide (default), change needs VLC restart "\
91                        "to apply.")
92 #define DEFAULT_AUDIO_DEVICE N_("Default Audio Device")
93
94 vlc_module_begin ()
95     set_shortname( "WaveOut" )
96     set_description( N_("Win32 waveOut extension output") )
97     set_capability( "audio output", 50 )
98     set_category( CAT_AUDIO )
99     set_subcategory( SUBCAT_AUDIO_AOUT )
100     add_bool( "waveout-float32", true, FLOAT_TEXT, FLOAT_LONGTEXT, true )
101
102     add_string( "waveout-audio-device", "wavemapper",
103                  DEVICE_TEXT, DEVICE_LONG, false )
104        add_deprecated_alias( "waveout-dev" )   /* deprecated since 0.9.3 */
105        change_string_list( ppsz_adev, ppsz_adev_text, ReloadWaveoutDevices )
106        change_need_restart ()
107        change_action_add( ReloadWaveoutDevices, N_("Refresh list") )
108
109     set_callbacks( Open, Close )
110 vlc_module_end ()
111
112 /*****************************************************************************
113  * aout_sys_t: waveOut audio output method descriptor
114  *****************************************************************************
115  * This structure is part of the audio output thread descriptor.
116  * It describes the waveOut specific properties of an audio device.
117  *****************************************************************************/
118 struct aout_sys_t
119 {
120     uint32_t i_wave_device_id;               /* ID of selected output device */
121
122     HWAVEOUT h_waveout;                        /* handle to waveout instance */
123
124     WAVEFORMATEXTENSIBLE waveformat;                         /* audio format */
125
126     WAVEHDR waveheader[FRAMES_NUM];
127
128     notification_thread_t *p_notif;                      /* WaveOutThread id */
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     aout_instance_t *p_aout = (aout_instance_t *)p_this;
154     vlc_value_t val;
155
156     /* Allocate structure */
157     p_aout->output.p_sys = malloc( sizeof( aout_sys_t ) );
158
159     if( p_aout->output.p_sys == NULL )
160         return VLC_ENOMEM;
161
162     p_aout->output.pf_play = Play;
163     p_aout->b_die = false;
164
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->output.p_sys->i_wave_device_id =
178          findDeviceID( psz_waveout_dev );
179
180     if(p_aout->output.p_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->output.p_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: %s", 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->output.p_sys );
219         return VLC_EGENERIC;
220     }
221
222
223     /* Open the device */
224     if( val.i_int == AOUT_VAR_SPDIF )
225     {
226         p_aout->output.output.i_format = VLC_CODEC_SPDIFL;
227
228         if( OpenWaveOut( p_aout,
229                          p_aout->output.p_sys->i_wave_device_id,
230                          VLC_CODEC_SPDIFL,
231                          p_aout->output.output.i_physical_channels,
232                          aout_FormatNbChannels( &p_aout->output.output ),
233                          p_aout->output.output.i_rate, false )
234             != VLC_SUCCESS )
235         {
236             msg_Err( p_aout, "cannot open waveout audio device" );
237             free( p_aout->output.p_sys );
238             return VLC_EGENERIC;
239         }
240
241         /* Calculate the frame size in bytes */
242         p_aout->output.i_nb_samples = A52_FRAME_NB;
243         p_aout->output.output.i_bytes_per_frame = AOUT_SPDIF_SIZE;
244         p_aout->output.output.i_frame_length = A52_FRAME_NB;
245         p_aout->output.p_sys->i_buffer_size =
246             p_aout->output.output.i_bytes_per_frame;
247
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->output.output.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->output.output.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->output.output.i_physical_channels = AOUT_CHAN_CENTER;
269             break;
270         default:
271             p_aout->output.output.i_physical_channels
272                     = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
273         }
274
275         if( OpenWaveOutPCM( p_aout,
276                             p_aout->output.p_sys->i_wave_device_id,
277                             &p_aout->output.output.i_format,
278                             p_aout->output.output.i_physical_channels,
279                             aout_FormatNbChannels( &p_aout->output.output ),
280                             p_aout->output.output.i_rate, false )
281             != VLC_SUCCESS )
282         {
283             msg_Err( p_aout, "cannot open waveout audio device" );
284             free( p_aout->output.p_sys );
285             return VLC_EGENERIC;
286         }
287
288         /* Calculate the frame size in bytes */
289         p_aout->output.i_nb_samples = FRAME_SIZE;
290         aout_FormatPrepare( &p_aout->output.output );
291         p_aout->output.p_sys->i_buffer_size = FRAME_SIZE *
292             p_aout->output.output.i_bytes_per_frame;
293
294         aout_VolumeSoftInit( p_aout );
295
296         /* Check for hardware volume support */
297         if( waveOutGetDevCaps( (UINT_PTR)p_aout->output.p_sys->h_waveout,
298                                &wocaps, sizeof(wocaps) ) == MMSYSERR_NOERROR &&
299             wocaps.dwSupport & WAVECAPS_VOLUME )
300         {
301             DWORD i_dummy;
302             if( waveOutGetVolume( p_aout->output.p_sys->h_waveout, &i_dummy )
303                 == MMSYSERR_NOERROR )
304             {
305                 p_aout->output.pf_volume_set = VolumeSet;
306             }
307         }
308     }
309
310
311     waveOutReset( p_aout->output.p_sys->h_waveout );
312
313     /* Allocate silence buffer */
314     p_aout->output.p_sys->p_silence_buffer =
315         malloc( p_aout->output.p_sys->i_buffer_size );
316     if( p_aout->output.p_sys->p_silence_buffer == NULL )
317     {
318         free( p_aout->output.p_sys );
319         return VLC_ENOMEM;
320     }
321     p_aout->output.p_sys->i_repeat_counter = 0;
322
323
324     /* Zero the buffer. WinCE doesn't have calloc(). */
325     memset( p_aout->output.p_sys->p_silence_buffer, 0,
326             p_aout->output.p_sys->i_buffer_size );
327
328     /* Now we need to setup our waveOut play notification structure */
329     p_aout->output.p_sys->p_notif =
330         vlc_object_create( p_aout, sizeof(notification_thread_t) );
331     p_aout->output.p_sys->p_notif->p_aout = p_aout;
332     p_aout->output.p_sys->event = CreateEvent( NULL, FALSE, FALSE, NULL );
333     p_aout->output.p_sys->new_buffer_event = CreateEvent( NULL, FALSE, FALSE, NULL );
334
335     /* define startpoint of playback on first call to play()
336       like alsa does (instead of playing a blank sample) */
337     p_aout->output.p_sys->b_playing = 0;
338     p_aout->output.p_sys->start_date = 0;
339
340
341     /* Then launch the notification thread */
342     if( vlc_thread_create( p_aout->output.p_sys->p_notif,
343                            WaveOutThread, VLC_THREAD_PRIORITY_OUTPUT ) )
344     {
345         msg_Err( p_aout, "cannot create WaveOutThread" );
346     }
347
348     /* We need to kick off the playback in order to have the callback properly
349      * working */
350     for( int i = 0; i < FRAMES_NUM; i++ )
351     {
352         p_aout->output.p_sys->waveheader[i].dwFlags = WHDR_DONE;
353         p_aout->output.p_sys->waveheader[i].dwUser = 0;
354     }
355
356     return VLC_SUCCESS;
357 }
358
359 /*****************************************************************************
360  * Probe: probe the audio device for available formats and channels
361  *****************************************************************************/
362 static void Probe( aout_instance_t * p_aout )
363 {
364     vlc_value_t val, text;
365     vlc_fourcc_t i_format;
366     unsigned int i_physical_channels;
367
368     var_Create( p_aout, "audio-device", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
369     text.psz_string = _("Audio Device");
370     var_Change( p_aout, "audio-device", VLC_VAR_SETTEXT, &text, NULL );
371
372     /* Test for 5.1 support */
373     i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
374                           AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT |
375                           AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE;
376     if( p_aout->output.output.i_physical_channels == i_physical_channels )
377     {
378         if( OpenWaveOutPCM( p_aout,
379                             p_aout->output.p_sys->i_wave_device_id,
380                             &i_format,
381                             i_physical_channels, 6,
382                             p_aout->output.output.i_rate, true )
383             == VLC_SUCCESS )
384         {
385             val.i_int = AOUT_VAR_5_1;
386             text.psz_string = (char *)_("5.1");
387             var_Change( p_aout, "audio-device",
388                         VLC_VAR_ADDCHOICE, &val, &text );
389             msg_Dbg( p_aout, "device supports 5.1 channels" );
390         }
391     }
392
393     /* Test for 2 Front 2 Rear support */
394     i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
395                           AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
396     if( ( p_aout->output.output.i_physical_channels & i_physical_channels )
397         == i_physical_channels )
398     {
399         if( OpenWaveOutPCM( p_aout,
400                             p_aout->output.p_sys->i_wave_device_id,
401                             &i_format,
402                             i_physical_channels, 4,
403                             p_aout->output.output.i_rate, true )
404             == VLC_SUCCESS )
405         {
406             val.i_int = AOUT_VAR_2F2R;
407             text.psz_string = (char *)_("2 Front 2 Rear");
408             var_Change( p_aout, "audio-device",
409                         VLC_VAR_ADDCHOICE, &val, &text );
410             msg_Dbg( p_aout, "device supports 4 channels" );
411         }
412     }
413
414     /* Test for stereo support */
415     i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
416     if( OpenWaveOutPCM( p_aout,
417                         p_aout->output.p_sys->i_wave_device_id,
418                         &i_format,
419                         i_physical_channels, 2,
420                         p_aout->output.output.i_rate, true )
421         == VLC_SUCCESS )
422     {
423         val.i_int = AOUT_VAR_STEREO;
424         text.psz_string = (char *)_("Stereo");
425         var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text );
426         msg_Dbg( p_aout, "device supports 2 channels" );
427     }
428
429     /* Test for mono support */
430     i_physical_channels = AOUT_CHAN_CENTER;
431     if( OpenWaveOutPCM( p_aout,
432                         p_aout->output.p_sys->i_wave_device_id,
433                         &i_format,
434                         i_physical_channels, 1,
435                         p_aout->output.output.i_rate, true )
436         == VLC_SUCCESS )
437     {
438         val.i_int = AOUT_VAR_MONO;
439         text.psz_string = (char *)_("Mono");
440         var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text );
441         msg_Dbg( p_aout, "device supports 1 channel" );
442     }
443
444     /* Test for SPDIF support */
445     if ( AOUT_FMT_NON_LINEAR( &p_aout->output.output ) )
446     {
447         if( OpenWaveOut( p_aout,
448                          p_aout->output.p_sys->i_wave_device_id,
449                          VLC_CODEC_SPDIFL,
450                          p_aout->output.output.i_physical_channels,
451                          aout_FormatNbChannels( &p_aout->output.output ),
452                          p_aout->output.output.i_rate, true )
453             == VLC_SUCCESS )
454         {
455             msg_Dbg( p_aout, "device supports A/52 over S/PDIF" );
456             val.i_int = AOUT_VAR_SPDIF;
457             text.psz_string = (char *)_("A/52 over S/PDIF");
458             var_Change( p_aout, "audio-device",
459                         VLC_VAR_ADDCHOICE, &val, &text );
460             if( var_InheritBool( p_aout, "spdif" ) )
461                 var_Set( p_aout, "audio-device", val );
462         }
463     }
464
465     var_Change( p_aout, "audio-device", VLC_VAR_CHOICESCOUNT, &val, NULL );
466     if( val.i_int <= 0 )
467     {
468         /* Probe() has failed. */
469         var_Destroy( p_aout, "audio-device" );
470         return;
471     }
472
473     var_AddCallback( p_aout, "audio-device", aout_ChannelsRestart, NULL );
474     var_TriggerCallback( p_aout, "intf-change" );
475 }
476
477 /*****************************************************************************
478  * Play: play a sound buffer
479  *****************************************************************************
480  * This doesn't actually play the buffer. This just stores the buffer so it
481  * can be played by the callback thread.
482  *****************************************************************************/
483 static void Play( aout_instance_t *_p_aout )
484 {
485     if( !_p_aout->output.p_sys->b_playing )
486     {
487         _p_aout->output.p_sys->b_playing = 1;
488
489         /* get the playing date of the first aout buffer */
490         _p_aout->output.p_sys->start_date =
491             aout_FifoFirstDate( _p_aout, &_p_aout->output.fifo );
492
493         msg_Dbg( _p_aout, "Wakeup sleeping output thread.");
494
495         /* wake up the audio output thread */
496         SetEvent( _p_aout->output.p_sys->event );
497     } else {
498         SetEvent( _p_aout->output.p_sys->new_buffer_event );
499     }
500 }
501
502 /*****************************************************************************
503  * Close: close the audio device
504  *****************************************************************************/
505 static void Close( vlc_object_t *p_this )
506 {
507     aout_instance_t *p_aout = (aout_instance_t *)p_this;
508     aout_sys_t *p_sys = p_aout->output.p_sys;
509
510     /* Before calling waveOutClose we must reset the device */
511     vlc_object_kill( p_aout );
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_thread_join( p_sys->p_notif );
518     vlc_object_release( p_sys->p_notif );
519
520     /*
521       kill the real output then - when the feed thread
522       is surely terminated!
523       old code could be too early in case that "feeding"
524       was running on termination
525
526       at this point now its sure, that there will be no new
527       data send to the driver, and we can cancel the last
528       running playbuffers
529     */
530     MMRESULT result = waveOutReset( p_sys->h_waveout );
531     if(result != MMSYSERR_NOERROR)
532     {
533        msg_Err( p_aout, "waveOutReset failed 0x%x", result );
534        /*
535         now we must wait, that all buffers are played
536         because cancel doesn't work in this case...
537        */
538        if(result == MMSYSERR_NOTSUPPORTED)
539        {
540            /*
541              clear currently played (done) buffers,
542              if returnvalue > 0 (means some buffer still playing)
543              wait for the driver event callback that one buffer
544              is finished with playing, and check again
545              the timeout of 5000ms is just, an emergency exit
546              of this loop, to avoid deadlock in case of other
547              (currently not known bugs, problems, errors cases?)
548            */
549            while(
550                  (WaveOutClearDoneBuffers( p_sys ) > 0)
551                  &&
552                  (WaitForSingleObject( p_sys->event, 5000) == WAIT_OBJECT_0)
553                 )
554            {
555                  msg_Dbg( p_aout, "Wait for waveout device...");
556            }
557        }
558     } else {
559         WaveOutClearDoneBuffers( p_sys );
560     }
561
562     /* now we can Close the device */
563     if( waveOutClose( p_sys->h_waveout ) != MMSYSERR_NOERROR )
564     {
565         msg_Err( p_aout, "waveOutClose failed" );
566     }
567
568     /*
569       because so long, the waveout device is playing, the callback
570       could occur and need the events
571     */
572     CloseHandle( p_sys->event );
573     CloseHandle( p_sys->new_buffer_event);
574
575     free( p_sys->p_silence_buffer );
576     free( p_sys );
577 }
578
579 /*****************************************************************************
580  * OpenWaveOut: open the waveout sound device
581  ****************************************************************************/
582 static int OpenWaveOut( aout_instance_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->output.p_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->output.p_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->output.p_sys->b_chan_reorder =
694         aout_CheckChannelReorder( pi_channels_in, pi_channels_out,
695                                   waveformat.dwChannelMask, i_nb_channels,
696                                   p_aout->output.p_sys->pi_chan_table );
697
698     if( p_aout->output.p_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( aout_instance_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( aout_instance_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->output.p_sys->p_silence_buffer,
764                        p_buffer->p_buffer,
765                        p_aout->output.p_sys->i_buffer_size );
766            p_aout->output.p_sys->i_repeat_counter = 2;
767         }
768     } else {
769         /* Use silence buffer instead */
770         if(p_aout->output.p_sys->i_repeat_counter)
771         {
772            p_aout->output.p_sys->i_repeat_counter--;
773            if(!p_aout->output.p_sys->i_repeat_counter)
774            {
775                vlc_memset( p_aout->output.p_sys->p_silence_buffer,
776                            0x00, p_aout->output.p_sys->i_buffer_size );
777            }
778         }
779         p_waveheader->lpData = (LPSTR)p_aout->output.p_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->output.p_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 _p_aout,
809                                       DWORD dwParam1, DWORD dwParam2 )
810 {
811     (void)h_waveout;    (void)dwParam1;    (void)dwParam2;
812     aout_instance_t *p_aout = (aout_instance_t *)_p_aout;
813     int i_queued_frames = 0;
814
815     if( uMsg != WOM_DONE ) return;
816
817     if( !vlc_object_alive (p_aout) ) 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->output.p_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->output.p_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( vlc_object_t *p_this )
879 {
880     notification_thread_t *p_notif = (notification_thread_t*)p_this;
881     aout_instance_t *p_aout = p_notif->p_aout;
882     aout_sys_t *p_sys = p_aout->output.p_sys;
883     aout_buffer_t *p_buffer = NULL;
884     WAVEHDR *p_waveheader = p_sys->waveheader;
885     int i, i_queued_frames;
886     bool b_sleek;
887     mtime_t next_date;
888     uint32_t i_buffer_length = 64;
889     int canc = vlc_savecancel ();
890
891     /* We don't want any resampling when using S/PDIF */
892     b_sleek = p_aout->output.output.i_format == VLC_CODEC_SPDIFL;
893
894     // wait for first call to "play()"
895     while( !p_sys->start_date && vlc_object_alive (p_aout) )
896            WaitForSingleObject( p_sys->event, INFINITE );
897     if( !vlc_object_alive (p_aout) )
898         return NULL;
899
900     msg_Dbg( p_aout, "will start to play in %"PRId64" us",
901              (p_sys->start_date - AOUT_PTS_TOLERANCE/4)-mdate());
902
903     // than wait a short time... before grabbing first frames
904     mwait( p_sys->start_date - AOUT_PTS_TOLERANCE/4 );
905
906 #define waveout_warn(msg) msg_Warn( p_aout, "aout_OutputNextBuffer no buffer "\
907                            "got next_date=%d ms, "\
908                            "%d frames to play, "\
909                            "starving? %d, %s",(int)(next_date/(mtime_t)1000), \
910                            i_queued_frames, \
911                            p_aout->output.b_starving, msg);
912     next_date = mdate();
913
914     while( vlc_object_alive (p_aout) )
915     {
916         /* Cleanup and find out the current latency */
917         i_queued_frames = WaveOutClearDoneBuffers( p_sys );
918
919         if( !vlc_object_alive (p_aout) ) return NULL;
920
921         /* Try to fill in as many frame buffers as possible */
922         for( i = 0; i < FRAMES_NUM; i++ )
923         {
924             /* Check if frame buf is available */
925             if( p_waveheader[i].dwFlags & WHDR_DONE )
926             {
927                 // next_date = mdate() + 1000000 * i_queued_frames /
928                 //  p_aout->output.output.i_rate * p_aout->output.i_nb_samples;
929
930                 // the realtime has got our back-site:) to come in sync
931                 if(next_date < mdate())
932                    next_date = mdate();
933
934
935                 /* Take into account the latency */
936                 p_buffer = aout_OutputNextBuffer( p_aout,
937                     next_date,
938                     b_sleek );
939
940                 if(!p_buffer)
941                 {
942 #if 0
943                     msg_Dbg( p_aout, "aout_OutputNextBuffer no buffer "\
944                                       "got next_date=%d ms, "\
945                                       "%d frames to play, "\
946                                       "starving? %d",(int)(next_date/(mtime_t)1000),
947                                                      i_queued_frames,
948                                                      p_aout->output.b_starving);
949 #endif
950                     if(p_aout->output.b_starving)
951                     {
952                         // means we are too early to request a new buffer?
953                         waveout_warn("waiting...")
954                         next_date = aout_FifoFirstDate( p_aout, &p_aout->output.fifo );
955                         mwait( next_date - AOUT_PTS_TOLERANCE/4 );
956                         next_date = mdate();
957                         p_buffer = aout_OutputNextBuffer( p_aout,
958                                      next_date,
959                                      b_sleek
960                                    );
961                     }
962                 }
963
964                 if( !p_buffer && i_queued_frames )
965                 {
966                     /* We aren't late so no need to play a blank sample */
967                     break;
968                 }
969
970                 if( p_buffer )
971                 {
972                     mtime_t buffer_length = p_buffer->i_length;
973                     next_date = next_date + buffer_length;
974                     i_buffer_length = buffer_length/1000;
975                 }
976
977                 /* Do the channel reordering */
978                 if( p_buffer && p_sys->b_chan_reorder )
979                 {
980                     aout_ChannelReorder( p_buffer->p_buffer,
981                         p_buffer->i_buffer,
982                         p_sys->waveformat.Format.nChannels,
983                         p_sys->pi_chan_table,
984                         p_sys->waveformat.Format.wBitsPerSample );
985                 }
986
987                 PlayWaveOut( p_aout, p_sys->h_waveout,
988                              &p_waveheader[i], p_buffer, b_sleek );
989
990                 i_queued_frames++;
991             }
992         }
993
994         if( !vlc_object_alive (p_aout) ) return NULL;
995
996         /*
997           deal with the case that the loop didn't fillup the buffer to the
998           max - instead of waiting that half the buffer is played before
999           fillup the waveout buffers, wait only for the next sample buffer
1000           to arrive at the play method...
1001
1002           this will also avoid, that the last buffer is play until the
1003           end, and then trying to get more data, so it will also
1004           work - if the next buffer will arrive some ms before the
1005           last buffer is finished.
1006         */
1007         if(i_queued_frames < FRAMES_NUM)
1008            WaitForSingleObject( p_sys->new_buffer_event, INFINITE );
1009         else
1010            WaitForSingleObject( p_sys->event, INFINITE );
1011
1012     }
1013
1014 #undef waveout_warn
1015     vlc_restorecancel (canc);
1016     return NULL;
1017 }
1018
1019 static int VolumeSet( aout_instance_t * p_aout, audio_volume_t i_volume,
1020                       bool mute )
1021 {
1022     if( mute )
1023         i_volume = AOUT_VOLUME_MIN;
1024
1025     unsigned long i_waveout_vol = i_volume * 0xFFFF * 2 / AOUT_VOLUME_MAX;
1026     i_waveout_vol |= (i_waveout_vol << 16);
1027
1028 #ifdef UNDER_CE
1029     waveOutSetVolume( 0, i_waveout_vol );
1030 #else
1031     waveOutSetVolume( p_aout->output.p_sys->h_waveout, i_waveout_vol );
1032 #endif
1033     return 0;
1034 }
1035
1036
1037 /*
1038   reload the configuration drop down list, of the Audio Devices
1039 */
1040 static int ReloadWaveoutDevices( vlc_object_t *p_this, char const *psz_name,
1041                                  vlc_value_t newval, vlc_value_t oldval, void *data )
1042 {
1043     VLC_UNUSED( newval ); VLC_UNUSED( oldval ); VLC_UNUSED( data );
1044
1045     module_config_t *p_item = config_FindConfig( p_this, psz_name );
1046     if( !p_item ) return VLC_SUCCESS;
1047
1048     /* Clear-up the current list */
1049     if( p_item->i_list )
1050     {
1051         int i;
1052
1053         /* Keep the first entry */
1054         for( i = 1; i < p_item->i_list; i++ )
1055         {
1056             free((char *)(p_item->ppsz_list[i]) );
1057             free((char *)(p_item->ppsz_list_text[i]) );
1058         }
1059         /* TODO: Remove when no more needed */
1060         p_item->ppsz_list[i] = NULL;
1061         p_item->ppsz_list_text[i] = NULL;
1062     }
1063     p_item->i_list = 1;
1064
1065     int wave_devices = waveOutGetNumDevs();
1066
1067     p_item->ppsz_list = xrealloc( p_item->ppsz_list,
1068                           (wave_devices+2) * sizeof(char *) );
1069     p_item->ppsz_list_text = xrealloc( p_item->ppsz_list_text,
1070                           (wave_devices+2) * sizeof(char *) );
1071
1072     WAVEOUTCAPS caps;
1073     char sz_dev_name[MAXPNAMELEN+32];
1074     int j=1;
1075     for(int i=0; i<wave_devices; i++)
1076     {
1077         if(waveOutGetDevCaps(i, &caps, sizeof(WAVEOUTCAPS))
1078            == MMSYSERR_NOERROR)
1079         {
1080           sprintf( sz_dev_name, psz_device_name_fmt, caps.szPname,
1081                                                caps.wMid,
1082                                                caps.wPid
1083                                               );
1084           p_item->ppsz_list[j] = FromLocaleDup( sz_dev_name );
1085           p_item->ppsz_list_text[j] = FromLocaleDup( sz_dev_name );
1086           p_item->i_list++;
1087           j++;
1088         }
1089
1090     }
1091     p_item->ppsz_list[j] = NULL;
1092     p_item->ppsz_list_text[j] = NULL;
1093
1094     /* Signal change to the interface */
1095     p_item->b_dirty = true;
1096
1097     return VLC_SUCCESS;
1098 }
1099
1100 /*
1101   convert devicename to device ID for output
1102   if device not found return WAVE_MAPPER, so let
1103   windows decide which preferred audio device
1104   should be used.
1105 */
1106 static uint32_t findDeviceID(char *psz_device_name)
1107 {
1108     if( !psz_device_name )
1109        return WAVE_MAPPER;
1110
1111     uint32_t wave_devices = waveOutGetNumDevs();
1112     WAVEOUTCAPS caps;
1113     char sz_dev_name[MAXPNAMELEN+32];
1114
1115     for( uint32_t i = 0; i < wave_devices; i++ )
1116     {
1117         if( waveOutGetDevCaps( i, &caps, sizeof(WAVEOUTCAPS) )
1118            == MMSYSERR_NOERROR)
1119         {
1120             sprintf( sz_dev_name, psz_device_name_fmt, caps.szPname,
1121                                                caps.wMid,
1122                                                caps.wPid
1123                                               );
1124             char *psz_temp = FromLocaleDup(sz_dev_name);
1125
1126             if( !stricmp(psz_temp, psz_device_name) )
1127             {
1128                 LocaleFree( psz_temp );
1129                 return i;
1130             }
1131             LocaleFree( psz_temp );
1132         }
1133     }
1134
1135     return WAVE_MAPPER;
1136 }