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