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