X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Faudio_output%2Fwaveout.c;h=de54f96b63d5d5ca8ea76bcbff8fd725a0ff5455;hb=d9cf7d2fbd21d3e29e1a88d4b285ff2a687eb629;hp=ffba414c3aa09727a5ec182c7b6313605797c72a;hpb=fefde73eb4bacb789ae41d4cad844cab119d6c34;p=vlc diff --git a/modules/audio_output/waveout.c b/modules/audio_output/waveout.c index ffba414c3a..de54f96b63 100644 --- a/modules/audio_output/waveout.c +++ b/modules/audio_output/waveout.c @@ -1,23 +1,23 @@ /***************************************************************************** * waveout.c : Windows waveOut plugin for vlc ***************************************************************************** - * Copyright (C) 2001-2009 the VideoLAN team + * Copyright (C) 2001-2009 VLC authors and VideoLAN * $Id$ * * Authors: Gildas Bazin * André Weber * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ @@ -30,10 +30,15 @@ # include "config.h" #endif +#include +#include +#include + +#define UNICODE #include #include #include -#include /* FromLocaleDup, LocaleFree */ +#include /* FromWide() */ #include #include "windows_audio_common.h" @@ -45,62 +50,33 @@ *****************************************************************************/ static int Open ( vlc_object_t * ); static void Close ( vlc_object_t * ); -static void Play ( aout_instance_t * ); +static void Play ( audio_output_t *, block_t * ); /***************************************************************************** * notification_thread_t: waveOut event thread *****************************************************************************/ /* local functions */ -static void Probe ( aout_instance_t * ); -static int OpenWaveOut ( aout_instance_t *, uint32_t, +static void Probe ( audio_output_t *, const audio_sample_format_t * ); +static int OpenWaveOut ( audio_output_t *, uint32_t, int, int, int, int, bool ); -static int OpenWaveOutPCM( aout_instance_t *, uint32_t, +static int OpenWaveOutPCM( audio_output_t *, uint32_t, vlc_fourcc_t*, int, int, int, bool ); -static int PlayWaveOut ( aout_instance_t *, HWAVEOUT, WAVEHDR *, - aout_buffer_t *, bool ); +static int PlayWaveOut ( audio_output_t *, HWAVEOUT, WAVEHDR *, + block_t *, bool ); -static void CALLBACK WaveOutCallback ( HWAVEOUT, UINT, DWORD, DWORD, DWORD ); +static void CALLBACK WaveOutCallback ( HWAVEOUT, UINT, DWORD_PTR, DWORD_PTR, DWORD_PTR ); static void* WaveOutThread( void * ); -static int VolumeSet( aout_instance_t *, audio_volume_t, bool ); +static int VolumeSet( audio_output_t *, float ); +static int MuteSet( audio_output_t *, bool ); static int WaveOutClearDoneBuffers(aout_sys_t *p_sys); -static int ReloadWaveoutDevices( vlc_object_t *, char const *, - vlc_value_t, vlc_value_t, void * ); +static int ReloadWaveoutDevices( vlc_object_t *, const char *, + char ***, char *** ); static uint32_t findDeviceID(char *); -static const char psz_device_name_fmt[] = "%s ($%x,$%x)"; - -static const char *const ppsz_adev[] = { "wavemapper", }; -static const char *const ppsz_adev_text[] = { N_("Microsoft Soundmapper") }; - - -/***************************************************************************** - * Module descriptor - *****************************************************************************/ -#define DEVICE_TEXT N_("Select Audio Device") -#define DEVICE_LONG N_("Select special Audio device, or let windows "\ - "decide (default), change needs VLC restart "\ - "to apply.") -#define DEFAULT_AUDIO_DEVICE N_("Default Audio Device") - -vlc_module_begin () - set_shortname( "WaveOut" ) - set_description( N_("Win32 waveOut extension output") ) - set_capability( "audio output", 50 ) - set_category( CAT_AUDIO ) - set_subcategory( SUBCAT_AUDIO_AOUT ) - add_bool( "waveout-float32", true, FLOAT_TEXT, FLOAT_LONGTEXT, true ) - - add_string( "waveout-audio-device", "wavemapper", - DEVICE_TEXT, DEVICE_LONG, false ) - add_deprecated_alias( "waveout-dev" ) /* deprecated since 0.9.3 */ - change_string_list( ppsz_adev, ppsz_adev_text, ReloadWaveoutDevices ) - change_action_add( ReloadWaveoutDevices, N_("Refresh list") ) - - set_callbacks( Open, Close ) -vlc_module_end () +static const wchar_t device_name_fmt[] = L"%ls ($%x,$%x)"; /***************************************************************************** * aout_sys_t: waveOut audio output method descriptor @@ -110,6 +86,7 @@ vlc_module_end () *****************************************************************************/ struct aout_sys_t { + aout_packet_t packet; uint32_t i_wave_device_id; /* ID of selected output device */ HWAVEOUT h_waveout; /* handle to waveout instance */ @@ -133,45 +110,70 @@ struct aout_sys_t uint8_t *p_silence_buffer; /* buffer we use to play silence */ - bool b_chan_reorder; /* do we need channel reordering */ - int pi_chan_table[AOUT_CHAN_MAX]; + union { + float volume; + float soft_gain; + }; + union { + bool mute; + bool soft_mute; + }; + + uint8_t chans_to_reorder; /* do we need channel reordering */ + uint8_t chan_table[AOUT_CHAN_MAX]; }; +#include "volume.h" + /***************************************************************************** - * Open: open the audio device - ***************************************************************************** - * This function opens and setups Win32 waveOut + * Module descriptor *****************************************************************************/ -static int Open( vlc_object_t *p_this ) -{ - aout_instance_t *p_aout = (aout_instance_t *)p_this; - vlc_value_t val; +#define DEVICE_TEXT N_("Select Audio Device") +#define DEVICE_LONG N_("Select special Audio device, or let windows "\ + "decide (default), change needs VLC restart "\ + "to apply.") +#define DEFAULT_AUDIO_DEVICE N_("Default Audio Device") - /* Allocate structure */ - p_aout->output.p_sys = malloc( sizeof( aout_sys_t ) ); +vlc_module_begin () + set_shortname( "WaveOut" ) + set_description( N_("Win32 waveOut extension output") ) + set_capability( "audio output", 50 ) + set_category( CAT_AUDIO ) + set_subcategory( SUBCAT_AUDIO_AOUT ) - if( p_aout->output.p_sys == NULL ) - return VLC_ENOMEM; + add_string( "waveout-audio-device", "wavemapper", + DEVICE_TEXT, DEVICE_LONG, false ) + change_string_cb( ReloadWaveoutDevices ) + add_sw_gain( ) - p_aout->output.pf_play = Play; - p_aout->b_die = false; + add_bool( "waveout-float32", true, FLOAT_TEXT, FLOAT_LONGTEXT, true ) + set_callbacks( Open, Close ) +vlc_module_end () - /* - initialize/update Device selection List - */ - ReloadWaveoutDevices( p_this, "waveout-audio-device", val, val, NULL); +/***************************************************************************** + * Opens the audio device + ***************************************************************************** + * This function opens and setups Win32 waveOut + *****************************************************************************/ +static int Start( audio_output_t *p_aout, audio_sample_format_t *restrict fmt ) +{ + vlc_value_t val; + p_aout->time_get = aout_PacketTimeGet; + p_aout->play = Play; + p_aout->pause = NULL; + p_aout->flush = aout_PacketFlush; /* check for configured audio device! */ char *psz_waveout_dev = var_CreateGetString( p_aout, "waveout-audio-device"); - p_aout->output.p_sys->i_wave_device_id = + p_aout->sys->i_wave_device_id = findDeviceID( psz_waveout_dev ); - if(p_aout->output.p_sys->i_wave_device_id == WAVE_MAPPER) + if(p_aout->sys->i_wave_device_id == WAVE_MAPPER) { if(psz_waveout_dev && stricmp(psz_waveout_dev,"wavemapper")) @@ -184,13 +186,13 @@ static int Open( vlc_object_t *p_this ) WAVEOUTCAPS waveoutcaps; - if(waveOutGetDevCaps( p_aout->output.p_sys->i_wave_device_id, + if(waveOutGetDevCaps( p_aout->sys->i_wave_device_id, &waveoutcaps, sizeof(WAVEOUTCAPS)) == MMSYSERR_NOERROR) { /* log debug some infos about driver, to know who to blame if it doesn't work */ - msg_Dbg( p_aout, "Drivername: %s", waveoutcaps.szPname); + msg_Dbg( p_aout, "Drivername: %ls", waveoutcaps.szPname); msg_Dbg( p_aout, "Driver Version: %d.%d", (waveoutcaps.vDriverVersion>>8)&255, waveoutcaps.vDriverVersion & 255); @@ -202,14 +204,14 @@ static int Open( vlc_object_t *p_this ) if( var_Type( p_aout, "audio-device" ) == 0 ) { - Probe( p_aout ); + Probe( p_aout, fmt ); } if( var_Get( p_aout, "audio-device", &val ) < 0 ) { /* Probe() has failed. */ var_Destroy( p_aout, "waveout-audio-device"); - free( p_aout->output.p_sys ); + free( p_aout->sys ); return VLC_EGENERIC; } @@ -217,29 +219,24 @@ static int Open( vlc_object_t *p_this ) /* Open the device */ if( val.i_int == AOUT_VAR_SPDIF ) { - p_aout->output.output.i_format = VLC_CODEC_SPDIFL; - - if( OpenWaveOut( p_aout, - p_aout->output.p_sys->i_wave_device_id, - VLC_CODEC_SPDIFL, - p_aout->output.output.i_physical_channels, - aout_FormatNbChannels( &p_aout->output.output ), - p_aout->output.output.i_rate, false ) + fmt->i_format = VLC_CODEC_SPDIFL; + + if( OpenWaveOut( p_aout, p_aout->sys->i_wave_device_id, + VLC_CODEC_SPDIFL, fmt->i_physical_channels, + aout_FormatNbChannels( fmt ), fmt->i_rate, false ) != VLC_SUCCESS ) { msg_Err( p_aout, "cannot open waveout audio device" ); - free( p_aout->output.p_sys ); + free( p_aout->sys ); return VLC_EGENERIC; } /* Calculate the frame size in bytes */ - p_aout->output.i_nb_samples = A52_FRAME_NB; - p_aout->output.output.i_bytes_per_frame = AOUT_SPDIF_SIZE; - p_aout->output.output.i_frame_length = A52_FRAME_NB; - p_aout->output.p_sys->i_buffer_size = - p_aout->output.output.i_bytes_per_frame; + fmt->i_bytes_per_frame = AOUT_SPDIF_SIZE; + fmt->i_frame_length = A52_FRAME_NB; + p_aout->sys->i_buffer_size = fmt->i_bytes_per_frame; - aout_VolumeNoneInit( p_aout ); + aout_PacketInit( p_aout, &p_aout->sys->packet, A52_FRAME_NB, fmt ); } else { @@ -248,90 +245,84 @@ static int Open( vlc_object_t *p_this ) switch( val.i_int ) { case AOUT_VAR_5_1: - p_aout->output.output.i_physical_channels + fmt->i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE; break; case AOUT_VAR_2F2R: - p_aout->output.output.i_physical_channels + fmt->i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT; break; case AOUT_VAR_MONO: - p_aout->output.output.i_physical_channels = AOUT_CHAN_CENTER; + fmt->i_physical_channels = AOUT_CHAN_CENTER; break; default: - p_aout->output.output.i_physical_channels - = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT; + fmt->i_physical_channels = AOUT_CHANS_STEREO; } - if( OpenWaveOutPCM( p_aout, - p_aout->output.p_sys->i_wave_device_id, - &p_aout->output.output.i_format, - p_aout->output.output.i_physical_channels, - aout_FormatNbChannels( &p_aout->output.output ), - p_aout->output.output.i_rate, false ) + if( OpenWaveOutPCM( p_aout, p_aout->sys->i_wave_device_id, + &fmt->i_format, fmt->i_physical_channels, + aout_FormatNbChannels( fmt ), fmt->i_rate, false ) != VLC_SUCCESS ) { msg_Err( p_aout, "cannot open waveout audio device" ); - free( p_aout->output.p_sys ); + free( p_aout->sys ); return VLC_EGENERIC; } /* Calculate the frame size in bytes */ - p_aout->output.i_nb_samples = FRAME_SIZE; - aout_FormatPrepare( &p_aout->output.output ); - p_aout->output.p_sys->i_buffer_size = FRAME_SIZE * - p_aout->output.output.i_bytes_per_frame; + aout_FormatPrepare( fmt ); + p_aout->sys->i_buffer_size = FRAME_SIZE * fmt->i_bytes_per_frame; - aout_VolumeSoftInit( p_aout ); + aout_PacketInit( p_aout, &p_aout->sys->packet, FRAME_SIZE, fmt ); /* Check for hardware volume support */ - if( waveOutGetDevCaps( (UINT_PTR)p_aout->output.p_sys->h_waveout, - &wocaps, sizeof(wocaps) ) == MMSYSERR_NOERROR && - wocaps.dwSupport & WAVECAPS_VOLUME ) - { - DWORD i_dummy; - if( waveOutGetVolume( p_aout->output.p_sys->h_waveout, &i_dummy ) - == MMSYSERR_NOERROR ) - { - p_aout->output.pf_volume_set = VolumeSet; - } + if( waveOutGetDevCaps( (UINT_PTR)p_aout->sys->h_waveout, + &wocaps, sizeof(wocaps) ) == MMSYSERR_NOERROR + && (wocaps.dwSupport & WAVECAPS_VOLUME) ) + { /* FIXME: this needs to be moved to Open() */ + p_aout->volume_set = VolumeSet; + p_aout->mute_set = MuteSet; + p_aout->sys->volume = 0xffff.fp0; + p_aout->sys->mute = false; } + else + aout_SoftVolumeInit( p_aout ); } - - waveOutReset( p_aout->output.p_sys->h_waveout ); + waveOutReset( p_aout->sys->h_waveout ); /* Allocate silence buffer */ - p_aout->output.p_sys->p_silence_buffer = - malloc( p_aout->output.p_sys->i_buffer_size ); - if( p_aout->output.p_sys->p_silence_buffer == NULL ) + p_aout->sys->p_silence_buffer = + malloc( p_aout->sys->i_buffer_size ); + if( p_aout->sys->p_silence_buffer == NULL ) { - free( p_aout->output.p_sys ); + aout_PacketDestroy( p_aout ); + free( p_aout->sys ); return VLC_ENOMEM; } - p_aout->output.p_sys->i_repeat_counter = 0; + p_aout->sys->i_repeat_counter = 0; /* Zero the buffer. WinCE doesn't have calloc(). */ - memset( p_aout->output.p_sys->p_silence_buffer, 0, - p_aout->output.p_sys->i_buffer_size ); + memset( p_aout->sys->p_silence_buffer, 0, + p_aout->sys->i_buffer_size ); /* Now we need to setup our waveOut play notification structure */ - p_aout->output.p_sys->event = CreateEvent( NULL, FALSE, FALSE, NULL ); - p_aout->output.p_sys->new_buffer_event = CreateEvent( NULL, FALSE, FALSE, NULL ); + p_aout->sys->event = CreateEvent( NULL, FALSE, FALSE, NULL ); + p_aout->sys->new_buffer_event = CreateEvent( NULL, FALSE, FALSE, NULL ); /* define startpoint of playback on first call to play() like alsa does (instead of playing a blank sample) */ - p_aout->output.p_sys->b_playing = 0; - p_aout->output.p_sys->start_date = 0; + p_aout->sys->b_playing = 0; + p_aout->sys->start_date = 0; /* Then launch the notification thread */ - vlc_atomic_set( &p_aout->output.p_sys->abort, 0); - if( vlc_clone( &p_aout->output.p_sys->thread, + vlc_atomic_set( &p_aout->sys->abort, 0); + if( vlc_clone( &p_aout->sys->thread, WaveOutThread, p_aout, VLC_THREAD_PRIORITY_OUTPUT ) ) { msg_Err( p_aout, "cannot create WaveOutThread" ); @@ -341,8 +332,8 @@ static int Open( vlc_object_t *p_this ) * working */ for( int i = 0; i < FRAMES_NUM; i++ ) { - p_aout->output.p_sys->waveheader[i].dwFlags = WHDR_DONE; - p_aout->output.p_sys->waveheader[i].dwUser = 0; + p_aout->sys->waveheader[i].dwFlags = WHDR_DONE; + p_aout->sys->waveheader[i].dwUser = 0; } return VLC_SUCCESS; @@ -351,7 +342,7 @@ static int Open( vlc_object_t *p_this ) /***************************************************************************** * Probe: probe the audio device for available formats and channels *****************************************************************************/ -static void Probe( aout_instance_t * p_aout ) +static void Probe( audio_output_t * p_aout, const audio_sample_format_t *fmt ) { vlc_value_t val, text; vlc_fourcc_t i_format; @@ -365,13 +356,11 @@ static void Probe( aout_instance_t * p_aout ) i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE; - if( p_aout->output.output.i_physical_channels == i_physical_channels ) + if( fmt->i_physical_channels == i_physical_channels ) { - if( OpenWaveOutPCM( p_aout, - p_aout->output.p_sys->i_wave_device_id, - &i_format, - i_physical_channels, 6, - p_aout->output.output.i_rate, true ) + if( OpenWaveOutPCM( p_aout, p_aout->sys->i_wave_device_id, + &i_format, i_physical_channels, 6, + fmt->i_rate, true ) == VLC_SUCCESS ) { val.i_int = AOUT_VAR_5_1; @@ -385,14 +374,12 @@ static void Probe( aout_instance_t * p_aout ) /* Test for 2 Front 2 Rear support */ i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT; - if( ( p_aout->output.output.i_physical_channels & i_physical_channels ) + if( ( fmt->i_physical_channels & i_physical_channels ) == i_physical_channels ) { - if( OpenWaveOutPCM( p_aout, - p_aout->output.p_sys->i_wave_device_id, - &i_format, - i_physical_channels, 4, - p_aout->output.output.i_rate, true ) + if( OpenWaveOutPCM( p_aout,p_aout->sys->i_wave_device_id, + &i_format, i_physical_channels, 4, + fmt->i_rate, true ) == VLC_SUCCESS ) { val.i_int = AOUT_VAR_2F2R; @@ -405,11 +392,9 @@ static void Probe( aout_instance_t * p_aout ) /* Test for stereo support */ i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT; - if( OpenWaveOutPCM( p_aout, - p_aout->output.p_sys->i_wave_device_id, - &i_format, - i_physical_channels, 2, - p_aout->output.output.i_rate, true ) + if( OpenWaveOutPCM( p_aout, p_aout->sys->i_wave_device_id, + &i_format,i_physical_channels, 2, + fmt->i_rate, true ) == VLC_SUCCESS ) { val.i_int = AOUT_VAR_STEREO; @@ -420,11 +405,8 @@ static void Probe( aout_instance_t * p_aout ) /* Test for mono support */ i_physical_channels = AOUT_CHAN_CENTER; - if( OpenWaveOutPCM( p_aout, - p_aout->output.p_sys->i_wave_device_id, - &i_format, - i_physical_channels, 1, - p_aout->output.output.i_rate, true ) + if( OpenWaveOutPCM( p_aout, p_aout->sys->i_wave_device_id, + &i_format, i_physical_channels, 1, fmt->i_rate, true ) == VLC_SUCCESS ) { val.i_int = AOUT_VAR_MONO; @@ -434,14 +416,11 @@ static void Probe( aout_instance_t * p_aout ) } /* Test for SPDIF support */ - if ( AOUT_FMT_NON_LINEAR( &p_aout->output.output ) ) + if ( AOUT_FMT_SPDIF( fmt ) ) { - if( OpenWaveOut( p_aout, - p_aout->output.p_sys->i_wave_device_id, - VLC_CODEC_SPDIFL, - p_aout->output.output.i_physical_channels, - aout_FormatNbChannels( &p_aout->output.output ), - p_aout->output.output.i_rate, true ) + if( OpenWaveOut( p_aout, p_aout->sys->i_wave_device_id, + VLC_CODEC_SPDIFL, fmt->i_physical_channels, + aout_FormatNbChannels( fmt ), fmt->i_rate, true ) == VLC_SUCCESS ) { msg_Dbg( p_aout, "device supports A/52 over S/PDIF" ); @@ -463,7 +442,6 @@ static void Probe( aout_instance_t * p_aout ) } var_AddCallback( p_aout, "audio-device", aout_ChannelsRestart, NULL ); - var_TriggerCallback( p_aout, "intf-change" ); } /***************************************************************************** @@ -472,32 +450,32 @@ static void Probe( aout_instance_t * p_aout ) * This doesn't actually play the buffer. This just stores the buffer so it * can be played by the callback thread. *****************************************************************************/ -static void Play( aout_instance_t *_p_aout ) +static void Play( audio_output_t *_p_aout, block_t *block ) { - if( !_p_aout->output.p_sys->b_playing ) + if( !_p_aout->sys->b_playing ) { - _p_aout->output.p_sys->b_playing = 1; + _p_aout->sys->b_playing = 1; /* get the playing date of the first aout buffer */ - _p_aout->output.p_sys->start_date = - aout_FifoFirstDate( &_p_aout->output.fifo ); + _p_aout->sys->start_date = block->i_pts; msg_Dbg( _p_aout, "Wakeup sleeping output thread."); /* wake up the audio output thread */ - SetEvent( _p_aout->output.p_sys->event ); + SetEvent( _p_aout->sys->event ); } else { - SetEvent( _p_aout->output.p_sys->new_buffer_event ); + SetEvent( _p_aout->sys->new_buffer_event ); } + + aout_PacketPlay( _p_aout, block ); } /***************************************************************************** * Close: close the audio device *****************************************************************************/ -static void Close( vlc_object_t *p_this ) +static void Stop( audio_output_t *p_aout ) { - aout_instance_t *p_aout = (aout_instance_t *)p_this; - aout_sys_t *p_sys = p_aout->output.p_sys; + aout_sys_t *p_sys = p_aout->sys; /* Before calling waveOutClose we must reset the device */ vlc_atomic_set( &p_sys->abort, 1); @@ -564,13 +542,13 @@ static void Close( vlc_object_t *p_this ) CloseHandle( p_sys->new_buffer_event); free( p_sys->p_silence_buffer ); - free( p_sys ); + aout_PacketDestroy( p_aout ); } /***************************************************************************** * OpenWaveOut: open the waveout sound device ****************************************************************************/ -static int OpenWaveOut( aout_instance_t *p_aout, uint32_t i_device_id, int i_format, +static int OpenWaveOut( audio_output_t *p_aout, uint32_t i_device_id, int i_format, int i_channels, int i_nb_channels, int i_rate, bool b_probe ) { @@ -578,14 +556,12 @@ static int OpenWaveOut( aout_instance_t *p_aout, uint32_t i_device_id, int i_for /* Set sound format */ -#define waveformat p_aout->output.p_sys->waveformat +#define waveformat p_aout->sys->waveformat waveformat.dwChannelMask = 0; - for( unsigned i = 0; i < sizeof(pi_channels_src)/sizeof(uint32_t); i++ ) - { - if( i_channels & pi_channels_src[i] ) + for( unsigned i = 0; pi_vlc_chan_order_wg4[i]; i++ ) + if( i_channels & pi_vlc_chan_order_wg4[i] ) waveformat.dwChannelMask |= pi_channels_in[i]; - } switch( i_format ) { @@ -661,7 +637,7 @@ static int OpenWaveOut( aout_instance_t *p_aout, uint32_t i_device_id, int i_for } /* Open the device */ - result = waveOutOpen( &p_aout->output.p_sys->h_waveout, i_device_id, + result = waveOutOpen( &p_aout->sys->h_waveout, i_device_id, (WAVEFORMATEX *)&waveformat, (DWORD_PTR)WaveOutCallback, (DWORD_PTR)p_aout, CALLBACK_FUNCTION | (b_probe?WAVE_FORMAT_QUERY:0) ); @@ -681,15 +657,12 @@ static int OpenWaveOut( aout_instance_t *p_aout, uint32_t i_device_id, int i_for return VLC_EGENERIC; } - p_aout->output.p_sys->b_chan_reorder = + p_aout->sys->chans_to_reorder = aout_CheckChannelReorder( pi_channels_in, pi_channels_out, - waveformat.dwChannelMask, i_nb_channels, - p_aout->output.p_sys->pi_chan_table ); - - if( p_aout->output.p_sys->b_chan_reorder ) - { + waveformat.dwChannelMask, + p_aout->sys->chan_table ); + if( p_aout->sys->chans_to_reorder ) msg_Dbg( p_aout, "channel reordering needed" ); - } return VLC_SUCCESS; @@ -700,7 +673,7 @@ static int OpenWaveOut( aout_instance_t *p_aout, uint32_t i_device_id, int i_for /***************************************************************************** * OpenWaveOutPCM: open a PCM waveout sound device ****************************************************************************/ -static int OpenWaveOutPCM( aout_instance_t *p_aout, uint32_t i_device_id, +static int OpenWaveOutPCM( audio_output_t *p_aout, uint32_t i_device_id, vlc_fourcc_t *i_format, int i_channels, int i_nb_channels, int i_rate, bool b_probe ) @@ -733,9 +706,8 @@ static int OpenWaveOutPCM( aout_instance_t *p_aout, uint32_t i_device_id, /***************************************************************************** * PlayWaveOut: play a buffer through the WaveOut device *****************************************************************************/ -static int PlayWaveOut( aout_instance_t *p_aout, HWAVEOUT h_waveout, - WAVEHDR *p_waveheader, aout_buffer_t *p_buffer, - bool b_spdif) +static int PlayWaveOut( audio_output_t *p_aout, HWAVEOUT h_waveout, + WAVEHDR *p_waveheader, block_t *p_buffer, bool b_spdif) { MMRESULT result; @@ -751,27 +723,27 @@ static int PlayWaveOut( aout_instance_t *p_aout, HWAVEOUT h_waveout, */ if(b_spdif) { - vlc_memcpy( p_aout->output.p_sys->p_silence_buffer, + memcpy( p_aout->sys->p_silence_buffer, p_buffer->p_buffer, - p_aout->output.p_sys->i_buffer_size ); - p_aout->output.p_sys->i_repeat_counter = 2; + p_aout->sys->i_buffer_size ); + p_aout->sys->i_repeat_counter = 2; } } else { /* Use silence buffer instead */ - if(p_aout->output.p_sys->i_repeat_counter) + if(p_aout->sys->i_repeat_counter) { - p_aout->output.p_sys->i_repeat_counter--; - if(!p_aout->output.p_sys->i_repeat_counter) + p_aout->sys->i_repeat_counter--; + if(!p_aout->sys->i_repeat_counter) { - vlc_memset( p_aout->output.p_sys->p_silence_buffer, - 0x00, p_aout->output.p_sys->i_buffer_size ); + memset( p_aout->sys->p_silence_buffer, + 0x00, p_aout->sys->i_buffer_size ); } } - p_waveheader->lpData = (LPSTR)p_aout->output.p_sys->p_silence_buffer; + p_waveheader->lpData = (LPSTR)p_aout->sys->p_silence_buffer; } p_waveheader->dwUser = p_buffer ? (DWORD_PTR)p_buffer : (DWORD_PTR)1; - p_waveheader->dwBufferLength = p_aout->output.p_sys->i_buffer_size; + p_waveheader->dwBufferLength = p_aout->sys->i_buffer_size; p_waveheader->dwFlags = 0; result = waveOutPrepareHeader( h_waveout, p_waveheader, sizeof(WAVEHDR) ); @@ -796,22 +768,22 @@ static int PlayWaveOut( aout_instance_t *p_aout, HWAVEOUT h_waveout, * WaveOutCallback: what to do once WaveOut has played its sound samples *****************************************************************************/ static void CALLBACK WaveOutCallback( HWAVEOUT h_waveout, UINT uMsg, - DWORD _p_aout, - DWORD dwParam1, DWORD dwParam2 ) + DWORD_PTR _p_aout, + DWORD_PTR dwParam1, DWORD_PTR dwParam2 ) { (void)h_waveout; (void)dwParam1; (void)dwParam2; - aout_instance_t *p_aout = (aout_instance_t *)_p_aout; + audio_output_t *p_aout = (audio_output_t *)_p_aout; int i_queued_frames = 0; if( uMsg != WOM_DONE ) return; - if( vlc_atomic_get(&p_aout->output.p_sys->abort) ) return; + if( vlc_atomic_get(&p_aout->sys->abort) ) return; /* Find out the current latency */ for( int i = 0; i < FRAMES_NUM; i++ ) { /* Check if frame buf is available */ - if( !(p_aout->output.p_sys->waveheader[i].dwFlags & WHDR_DONE) ) + if( !(p_aout->sys->waveheader[i].dwFlags & WHDR_DONE) ) { i_queued_frames++; } @@ -819,12 +791,12 @@ static void CALLBACK WaveOutCallback( HWAVEOUT h_waveout, UINT uMsg, /* Don't wake up the thread too much */ if( i_queued_frames <= FRAMES_NUM/2 ) - SetEvent( p_aout->output.p_sys->event ); + SetEvent( p_aout->sys->event ); } /**************************************************************************** - * WaveOutClearDoneBuffers: Clear all done marked buffers, and free aout_bufer + * WaveOutClearDoneBuffers: Clear all done marked buffers, and free buffer **************************************************************************** * return value is the number of still playing buffers in the queue ****************************************************************************/ @@ -838,14 +810,14 @@ static int WaveOutClearDoneBuffers(aout_sys_t *p_sys) if( (p_waveheader[i].dwFlags & WHDR_DONE) && p_waveheader[i].dwUser ) { - aout_buffer_t *p_buffer = - (aout_buffer_t *)(p_waveheader[i].dwUser); + block_t *p_buffer = + (block_t *)(p_waveheader[i].dwUser); /* Unprepare and free the buffers which has just been played */ waveOutUnprepareHeader( p_sys->h_waveout, &p_waveheader[i], sizeof(WAVEHDR) ); if( p_waveheader[i].dwUser != 1 ) - aout_BufferFree( p_buffer ); + block_Release( p_buffer ); p_waveheader[i].dwUser = 0; } @@ -868,44 +840,43 @@ static int WaveOutClearDoneBuffers(aout_sys_t *p_sys) *****************************************************************************/ static void* WaveOutThread( void *data ) { - aout_instance_t *p_aout = data; - aout_sys_t *p_sys = p_aout->output.p_sys; - aout_buffer_t *p_buffer = NULL; + audio_output_t *p_aout = data; + aout_sys_t *p_sys = p_aout->sys; + block_t *p_buffer = NULL; WAVEHDR *p_waveheader = p_sys->waveheader; int i, i_queued_frames; bool b_sleek; mtime_t next_date; - uint32_t i_buffer_length = 64; int canc = vlc_savecancel (); /* We don't want any resampling when using S/PDIF */ - b_sleek = p_aout->output.output.i_format == VLC_CODEC_SPDIFL; + b_sleek = p_sys->packet.format.i_format == VLC_CODEC_SPDIFL; // wait for first call to "play()" - while( !p_sys->start_date && !vlc_atomic_get(&p_aout->output.p_sys->abort) ) + while( !p_sys->start_date && !vlc_atomic_get(&p_aout->sys->abort) ) WaitForSingleObject( p_sys->event, INFINITE ); - if( vlc_atomic_get(&p_aout->output.p_sys->abort) ) + if( vlc_atomic_get(&p_aout->sys->abort) ) return NULL; msg_Dbg( p_aout, "will start to play in %"PRId64" us", - (p_sys->start_date - AOUT_PTS_TOLERANCE/4)-mdate()); + (p_sys->start_date - AOUT_MAX_PTS_ADVANCE/4)-mdate()); // than wait a short time... before grabbing first frames - mwait( p_sys->start_date - AOUT_PTS_TOLERANCE/4 ); + mwait( p_sys->start_date - AOUT_MAX_PTS_ADVANCE/4 ); -#define waveout_warn(msg) msg_Warn( p_aout, "aout_OutputNextBuffer no buffer "\ +#define waveout_warn(msg) msg_Warn( p_aout, "aout_PacketNext no buffer "\ "got next_date=%d ms, "\ "%d frames to play, %s",\ (int)(next_date/(mtime_t)1000), \ i_queued_frames, msg); next_date = mdate(); - while( !vlc_atomic_get(&p_aout->output.p_sys->abort) ) + while( !vlc_atomic_get(&p_aout->sys->abort) ) { /* Cleanup and find out the current latency */ i_queued_frames = WaveOutClearDoneBuffers( p_sys ); - if( vlc_atomic_get(&p_aout->output.p_sys->abort) ) return NULL; + if( vlc_atomic_get(&p_aout->sys->abort) ) return NULL; /* Try to fill in as many frame buffers as possible */ for( i = 0; i < FRAMES_NUM; i++ ) @@ -914,7 +885,7 @@ static void* WaveOutThread( void *data ) if( p_waveheader[i].dwFlags & WHDR_DONE ) { // next_date = mdate() + 1000000 * i_queued_frames / - // p_aout->output.output.i_rate * p_aout->output.i_nb_samples; + // p_aout->format.i_rate * p_aout->i_nb_samples; // the realtime has got our back-site:) to come in sync if(next_date < mdate()) @@ -922,26 +893,19 @@ static void* WaveOutThread( void *data ) /* Take into account the latency */ - p_buffer = aout_OutputNextBuffer( p_aout, - next_date, - b_sleek ); - + p_buffer = aout_PacketNext( p_aout, next_date ); if(!p_buffer) { #if 0 - msg_Dbg( p_aout, "aout_OutputNextBuffer no buffer " - "got next_date=%d ms, " - "%d frames to play", - (int)(next_date/(mtime_t)1000), - i_queued_frames); + msg_Dbg( p_aout, "aout_PacketNext no buffer got " + "next_date=%"PRId64" ms, %d frames to play", + next_date/1000, i_queued_frames); #endif // means we are too early to request a new buffer? waveout_warn("waiting...") - next_date = aout_FifoFirstDate( &p_aout->output.fifo ); - mwait( next_date - AOUT_PTS_TOLERANCE/4 ); + mwait( next_date - AOUT_MAX_PTS_ADVANCE/4 ); next_date = mdate(); - p_buffer = aout_OutputNextBuffer( p_aout, next_date, - b_sleek ); + p_buffer = aout_PacketNext( p_aout, next_date ); } if( !p_buffer && i_queued_frames ) @@ -954,16 +918,15 @@ static void* WaveOutThread( void *data ) { mtime_t buffer_length = p_buffer->i_length; next_date = next_date + buffer_length; - i_buffer_length = buffer_length/1000; } /* Do the channel reordering */ - if( p_buffer && p_sys->b_chan_reorder ) + if( p_buffer && p_sys->chans_to_reorder ) { aout_ChannelReorder( p_buffer->p_buffer, p_buffer->i_buffer, p_sys->waveformat.Format.nChannels, - p_sys->pi_chan_table, + p_sys->chan_table, p_sys->waveformat.Format.wBitsPerSample ); } @@ -974,7 +937,7 @@ static void* WaveOutThread( void *data ) } } - if( vlc_atomic_get(&p_aout->output.p_sys->abort) ) return NULL; + if( vlc_atomic_get(&p_aout->sys->abort) ) return NULL; /* deal with the case that the loop didn't fillup the buffer to the @@ -999,85 +962,70 @@ static void* WaveOutThread( void *data ) return NULL; } -static int VolumeSet( aout_instance_t * p_aout, audio_volume_t i_volume, - bool mute ) +static int VolumeSet( audio_output_t *aout, float volume ) { - if( mute ) - i_volume = AOUT_VOLUME_MIN; + aout_sys_t *sys = aout->sys; + const HWAVEOUT hwo = sys->h_waveout; + const float full = 0xffff.fp0; - unsigned long i_waveout_vol = i_volume * 0xFFFF * 2 / AOUT_VOLUME_MAX; - i_waveout_vol |= (i_waveout_vol << 16); + volume *= full; + if( volume >= full ) + return -1; -#ifdef UNDER_CE - waveOutSetVolume( 0, i_waveout_vol ); -#else - waveOutSetVolume( p_aout->output.p_sys->h_waveout, i_waveout_vol ); -#endif + sys->volume = volume; + if( sys->mute ) + return 0; + + uint16_t vol = lroundf(volume); + waveOutSetVolume( hwo, vol | (vol << 16) ); return 0; } +static int MuteSet( audio_output_t * p_aout, bool mute ) +{ + aout_sys_t *sys = p_aout->sys; + const HWAVEOUT hwo = sys->h_waveout; + uint16_t vol = mute ? 0 : lroundf(sys->volume); + + sys->mute = mute; + waveOutSetVolume( hwo, vol | (vol << 16) ); + return 0; +} /* reload the configuration drop down list, of the Audio Devices */ static int ReloadWaveoutDevices( vlc_object_t *p_this, char const *psz_name, - vlc_value_t newval, vlc_value_t oldval, void *data ) + char ***values, char ***descs ) { - VLC_UNUSED( newval ); VLC_UNUSED( oldval ); VLC_UNUSED( data ); + int n = 0, nb_devices = waveOutGetNumDevs(); - module_config_t *p_item = config_FindConfig( p_this, psz_name ); - if( !p_item ) return VLC_SUCCESS; + VLC_UNUSED( p_this); VLC_UNUSED( psz_name ); - /* Clear-up the current list */ - if( p_item->i_list ) - { - int i; + *values = xmalloc( (nb_devices + 1) * sizeof(char *) ); + *descs = xmalloc( (nb_devices + 1) * sizeof(char *) ); - /* Keep the first entry */ - for( i = 1; i < p_item->i_list; i++ ) - { - free((char *)(p_item->ppsz_list[i]) ); - free((char *)(p_item->ppsz_list_text[i]) ); - } - /* TODO: Remove when no more needed */ - p_item->ppsz_list[i] = NULL; - p_item->ppsz_list_text[i] = NULL; - } - p_item->i_list = 1; - - int wave_devices = waveOutGetNumDevs(); - - p_item->ppsz_list = xrealloc( p_item->ppsz_list, - (wave_devices+2) * sizeof(char *) ); - p_item->ppsz_list_text = xrealloc( p_item->ppsz_list_text, - (wave_devices+2) * sizeof(char *) ); + (*values)[n] = strdup( "wavemapper" ); + (*descs)[n] = strdup( _("Microsoft Soundmapper") ); + n++; - WAVEOUTCAPS caps; - char sz_dev_name[MAXPNAMELEN+32]; - int j=1; - for(int i=0; ippsz_list[j] = FromLocaleDup( sz_dev_name ); - p_item->ppsz_list_text[j] = FromLocaleDup( sz_dev_name ); - p_item->i_list++; - j++; - } + WAVEOUTCAPS caps; + wchar_t dev_name[MAXPNAMELEN+32]; + if(waveOutGetDevCaps(i, &caps, sizeof(WAVEOUTCAPS)) + != MMSYSERR_NOERROR) + continue; + + _snwprintf(dev_name, MAXPNAMELEN + 32, device_name_fmt, + caps.szPname, caps.wMid, caps.wPid); + (*values)[n] = FromWide( dev_name ); + (*descs)[n] = strdup( (*values)[n] ); + n++; } - p_item->ppsz_list[j] = NULL; - p_item->ppsz_list_text[j] = NULL; - - /* Signal change to the interface */ - p_item->b_dirty = true; - return VLC_SUCCESS; + return n; } /* @@ -1092,28 +1040,48 @@ static uint32_t findDeviceID(char *psz_device_name) return WAVE_MAPPER; uint32_t wave_devices = waveOutGetNumDevs(); - WAVEOUTCAPS caps; - char sz_dev_name[MAXPNAMELEN+32]; for( uint32_t i = 0; i < wave_devices; i++ ) { + WAVEOUTCAPS caps; + wchar_t dev_name[MAXPNAMELEN+32]; + if( waveOutGetDevCaps( i, &caps, sizeof(WAVEOUTCAPS) ) - == MMSYSERR_NOERROR) - { - sprintf( sz_dev_name, psz_device_name_fmt, caps.szPname, - caps.wMid, - caps.wPid - ); - char *psz_temp = FromLocaleDup(sz_dev_name); + != MMSYSERR_NOERROR ) + continue; - if( !stricmp(psz_temp, psz_device_name) ) - { - LocaleFree( psz_temp ); - return i; - } - LocaleFree( psz_temp ); + _snwprintf( dev_name, MAXPNAMELEN + 32, device_name_fmt, + caps.szPname, caps.wMid, caps.wPid ); + char *u8 = FromWide(dev_name); + if( !stricmp(u8, psz_device_name) ) + { + free( u8 ); + return i; } + free( u8 ); } return WAVE_MAPPER; } + +static int Open(vlc_object_t *obj) +{ + audio_output_t *aout = (audio_output_t *)obj; + aout_sys_t *sys = malloc(sizeof (*sys)); + + if (unlikely(sys == NULL)) + return VLC_ENOMEM; + aout->sys = sys; + aout->start = Start; + aout->stop = Stop; + /* FIXME: volume handlers */ + return VLC_SUCCESS; +} + +static void Close(vlc_object_t *obj) +{ + audio_output_t *aout = (audio_output_t *)obj; + aout_sys_t *sys = aout->sys; + + free(sys); +}