Commit 5bbe0409 authored by gbazin's avatar gbazin
Browse files

* modules/video_output/directx/aout.c: adapted the directx audio plugin to aout3.
* modules/audio_output/waveout.c: adapted the waveout audio plugin to aout3 and
decreased its score so the directx plugin is selected by default.
* configure.in: re-enabled the waveout plugin

It's really amazing how much aout3 simplifies these plugins :)
parent f8ec3801
......@@ -1473,7 +1473,7 @@ AC_ARG_ENABLE(waveout,
[ --enable-waveout Win32 waveOut module (default enabled on Win32)])
if test "x${enable_waveout}" != "xno" -a "x${SYS}" = "xmingw32"
then
#PLUGINS="${PLUGINS} audio_output/waveout"
PLUGINS="${PLUGINS} audio_output/waveout"
waveout_LDFLAGS="-lwinmm"
fi
......
......@@ -2,7 +2,7 @@
* waveout.c : Windows waveOut plugin for vlc
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: waveout.c,v 1.1 2002/08/07 21:36:55 massiot Exp $
* $Id: waveout.c,v 1.2 2002/08/10 18:17:06 gbazin Exp $
*
* Authors: Gildas Bazin <gbazin@netcourrier.com>
*
......@@ -32,28 +32,36 @@
#include <vlc/vlc.h>
#include <vlc/aout.h>
#include "aout_internal.h"
#include <mmsystem.h>
#define FRAME_SIZE 2048 /* The size is in samples, not in bytes */
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int Open ( vlc_object_t * );
static void Close ( vlc_object_t * );
static int SetFormat ( aout_thread_t * );
static int GetBufInfo ( aout_thread_t *, int );
static void Play ( aout_thread_t *, byte_t *, int );
static int SetFormat ( aout_instance_t * );
static void Play ( aout_instance_t *, aout_buffer_t * );
/* local functions */
static int OpenWaveOutDevice( aout_thread_t *p_aout );
static int OpenWaveOut ( aout_instance_t *p_aout, int i_format,
int i_channels, int i_rate );
static int PlayWaveOut ( aout_instance_t *, HWAVEOUT, WAVEHDR *,
aout_buffer_t * );
static void CALLBACK WaveOutCallback ( HWAVEOUT h_waveout, UINT uMsg,
DWORD _p_aout,
DWORD dwParam1, DWORD dwParam2 );
/*****************************************************************************
* Module descriptor
*****************************************************************************/
vlc_module_begin();
set_description( _("Win32 waveOut extension module") );
set_capability( "audio output", 250 );
set_capability( "audio output", 50 );
set_callbacks( Open, Close );
vlc_module_end();
......@@ -63,20 +71,17 @@ vlc_module_end();
* This structure is part of the audio output thread descriptor.
* It describes the waveOut specific properties of an audio device.
*****************************************************************************/
#define NUMBUF 3 /* We use triple buffering to be on the safe side */
struct aout_sys_t
{
HWAVEOUT h_waveout; /* handle to waveout instance */
WAVEFORMATEX waveformat; /* Audio format */
WAVEFORMATEX waveformat; /* audio format */
WAVEHDR waveheader[NUMBUF];
WAVEHDR waveheader[2];
int i_current_buffer;
int i_buffer_size;
DWORD dw_counter; /* Number of bytes played since beginning */
byte_t *p_silence_buffer; /* buffer we use to play silence */
};
/*****************************************************************************
......@@ -86,29 +91,35 @@ struct aout_sys_t
*****************************************************************************/
static int Open( vlc_object_t *p_this )
{
aout_thread_t *p_aout = (aout_thread_t *)p_this;
int i;
aout_instance_t *p_aout = (aout_instance_t *)p_this;
/* Allocate structure */
p_aout->p_sys = malloc( sizeof( aout_sys_t ) );
p_aout->output.p_sys = malloc( sizeof( aout_sys_t ) );
if( p_aout->p_sys == NULL )
if( p_aout->output.p_sys == NULL )
{
msg_Err( p_aout, "out of memory" );
return( 1 );
return 1;
}
p_aout->pf_setformat = SetFormat;
p_aout->pf_getbufinfo = GetBufInfo;
p_aout->pf_play = Play;
/* Initialize some variables */
p_aout->p_sys->i_current_buffer = 0;
for( i=0; i<NUMBUF; i++)
p_aout->p_sys->waveheader[i].lpData = malloc( 1 );
p_aout->output.pf_setformat = SetFormat;
p_aout->output.pf_play = Play;
return OpenWaveOutDevice( p_aout );
/* calculate the frame size in bytes */
p_aout->output.p_sys->i_buffer_size = FRAME_SIZE * sizeof(s16)
* p_aout->output.p_sys->waveformat.nChannels;
/* Allocate silence buffer */
p_aout->output.p_sys->p_silence_buffer =
calloc( p_aout->output.p_sys->i_buffer_size, 1 );
if( p_aout->output.p_sys->p_silence_buffer == NULL )
{
msg_Err( p_aout, "out of memory" );
return 1;
}
/* We need to open the device with default values to be sure it is
* available */
return OpenWaveOut( p_aout, WAVE_FORMAT_PCM, 2, 44100 );
}
/*****************************************************************************
......@@ -118,108 +129,66 @@ static int Open( vlc_object_t *p_this )
* For this we need to close the current device and create another
* one with the desired format.
*****************************************************************************/
static int SetFormat( aout_thread_t *p_aout )
static int SetFormat( aout_instance_t *p_aout )
{
msg_Dbg( p_aout, "SetFormat" );
/* Check if the format has changed */
waveOutReset( p_aout->output.p_sys->h_waveout );
if( (p_aout->p_sys->waveformat.nChannels != p_aout->i_channels) ||
(p_aout->p_sys->waveformat.nSamplesPerSec != p_aout->i_rate) )
{
/* Before calling waveOutClose we must reset the device */
waveOutReset( p_aout->p_sys->h_waveout );
p_aout->output.output.i_format = AOUT_FMT_S16_NE;
p_aout->output.i_nb_samples = FRAME_SIZE;
if( waveOutClose( p_aout->p_sys->h_waveout ) != MMSYSERR_NOERROR )
/* Check if the format has changed */
if( (p_aout->output.p_sys->waveformat.nChannels !=
p_aout->output.output.i_channels) ||
(p_aout->output.p_sys->waveformat.nSamplesPerSec !=
p_aout->output.output.i_rate) )
{
if( waveOutClose( p_aout->output.p_sys->h_waveout ) !=
MMSYSERR_NOERROR )
{
msg_Err( p_aout, "waveOutClose failed" );
}
return OpenWaveOutDevice( p_aout );
}
return 0;
}
/* calculate the frame size in bytes */
p_aout->output.p_sys->i_buffer_size = FRAME_SIZE * sizeof(s16)
* p_aout->output.output.i_channels;
/*****************************************************************************
* GetBufInfo: buffer status query
*****************************************************************************
* returns the number of bytes in the audio buffer that have not yet been
* sent to the sound device.
*****************************************************************************/
static int GetBufInfo( aout_thread_t *p_aout, int i_buffer_limit )
{
MMTIME mmtime;
/* take care of silence buffer */
free( p_aout->output.p_sys->p_silence_buffer );
p_aout->output.p_sys->p_silence_buffer =
calloc( p_aout->output.p_sys->i_buffer_size, 1 );
if( p_aout->output.p_sys->p_silence_buffer == NULL )
{
msg_Err( p_aout, "out of memory" );
return 1;
}
mmtime.wType = TIME_BYTES;
if( (waveOutGetPosition(p_aout->p_sys->h_waveout, &mmtime, sizeof(MMTIME)))
!= MMSYSERR_NOERROR || (mmtime.wType != TIME_BYTES) )
{
msg_Warn( p_aout, "waveOutGetPosition failed" );
return i_buffer_limit;
if( OpenWaveOut( p_aout, WAVE_FORMAT_PCM,
p_aout->output.output.i_channels,
p_aout->output.output.i_rate ) )
return 1;
}
/* We need to kick off the playback in order to have the callback properly
* working */
PlayWaveOut( p_aout, p_aout->output.p_sys->h_waveout,
&p_aout->output.p_sys->waveheader[0], NULL );
PlayWaveOut( p_aout, p_aout->output.p_sys->h_waveout,
&p_aout->output.p_sys->waveheader[1], NULL );
#if 0
msg_Dbg( p_aout, "GetBufInfo: %i",
p_aout->p_sys->dw_counter - mmtime.u.cb );
#endif
return (p_aout->p_sys->dw_counter - mmtime.u.cb);
return 0;
}
/*****************************************************************************
* Play: play a sound buffer
*****************************************************************************
* This function writes a buffer of i_length bytes
* 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_thread_t *p_aout, byte_t *p_buffer, int i_size )
static void Play( aout_instance_t *p_aout, aout_buffer_t *p_buffer )
{
MMRESULT result;
int current_buffer = p_aout->p_sys->i_current_buffer;
p_aout->p_sys->i_current_buffer = (current_buffer + 1) % NUMBUF;
/* Unprepare the old buffer */
waveOutUnprepareHeader( p_aout->p_sys->h_waveout,
&p_aout->p_sys->waveheader[current_buffer],
sizeof(WAVEHDR) );
/* Prepare the buffer */
p_aout->p_sys->waveheader[current_buffer].lpData =
realloc( p_aout->p_sys->waveheader[current_buffer].lpData, i_size );
if( !p_aout->p_sys->waveheader[current_buffer].lpData )
{
msg_Err( p_aout, "could not allocate buffer" );
return;
}
p_aout->p_sys->waveheader[current_buffer].dwBufferLength = i_size;
p_aout->p_sys->waveheader[current_buffer].dwFlags = 0;
result = waveOutPrepareHeader( p_aout->p_sys->h_waveout,
&p_aout->p_sys->waveheader[current_buffer],
sizeof(WAVEHDR) );
if( result != MMSYSERR_NOERROR )
{
msg_Err( p_aout, "waveOutPrepareHeader failed" );
return;
}
/* Send the buffer the waveOut queue */
p_aout->p_vlc->pf_memcpy( p_aout->p_sys->waveheader[current_buffer].lpData,
p_buffer, i_size );
result = waveOutWrite( p_aout->p_sys->h_waveout,
&p_aout->p_sys->waveheader[current_buffer],
sizeof(WAVEHDR) );
if( result != MMSYSERR_NOERROR )
{
msg_Err( p_aout, "waveOutWrite failed" );
return;
}
/* keep track of number of bytes played */
p_aout->p_sys->dw_counter += i_size;
aout_FifoPush( p_aout, &p_aout->output.fifo, p_buffer );
}
/*****************************************************************************
......@@ -227,60 +196,122 @@ static void Play( aout_thread_t *p_aout, byte_t *p_buffer, int i_size )
*****************************************************************************/
static void Close( vlc_object_t *p_this )
{
aout_thread_t *p_aout = (aout_thread_t *)p_this;
int i;
aout_instance_t *p_aout = (aout_instance_t *)p_this;
/* Before calling waveOutClose we must reset the device */
waveOutReset( p_aout->p_sys->h_waveout );
waveOutReset( p_aout->output.p_sys->h_waveout );
/* Close the device */
if( waveOutClose( p_aout->p_sys->h_waveout ) != MMSYSERR_NOERROR )
if( waveOutClose( p_aout->output.p_sys->h_waveout ) != MMSYSERR_NOERROR )
{
msg_Err( p_aout, "waveOutClose failed" );
}
/* Deallocate memory */
for( i=0; i<NUMBUF; i++ )
free( p_aout->p_sys->waveheader[i].lpData );
/* Free silence buffer */
free( p_aout->output.p_sys->p_silence_buffer );
if( p_aout->p_sys != NULL )
if( p_aout->output.p_sys != NULL )
{
free( p_aout->p_sys );
p_aout->p_sys = NULL;
free( p_aout->output.p_sys );
p_aout->output.p_sys = NULL;
}
}
/*****************************************************************************
* OpenWaveOutDevice: open the sound device
* OpenWaveOut: open the waveout sound device
****************************************************************************/
static int OpenWaveOutDevice( aout_thread_t *p_aout )
static int OpenWaveOut( aout_instance_t *p_aout, int i_format,
int i_channels, int i_rate )
{
MMRESULT result;
/* initialize played bytes counter */
p_aout->p_sys->dw_counter = 0;
/* Set sound format */
p_aout->p_sys->waveformat.wFormatTag = WAVE_FORMAT_PCM;
p_aout->p_sys->waveformat.nChannels = p_aout->i_channels;
p_aout->p_sys->waveformat.nSamplesPerSec = p_aout->i_rate;
p_aout->p_sys->waveformat.wBitsPerSample = 16;
p_aout->p_sys->waveformat.nBlockAlign =
p_aout->p_sys->waveformat.wBitsPerSample / 8 * p_aout->i_channels;
p_aout->p_sys->waveformat.nAvgBytesPerSec =
p_aout->p_sys->waveformat.nSamplesPerSec *
p_aout->p_sys->waveformat.nBlockAlign;
p_aout->output.p_sys->waveformat.wFormatTag = i_format;
p_aout->output.p_sys->waveformat.nChannels = i_channels;
p_aout->output.p_sys->waveformat.nSamplesPerSec = i_rate;
p_aout->output.p_sys->waveformat.wBitsPerSample = 16;
p_aout->output.p_sys->waveformat.nBlockAlign =
p_aout->output.p_sys->waveformat.wBitsPerSample / 8 * i_channels;
p_aout->output.p_sys->waveformat.nAvgBytesPerSec =
p_aout->output.p_sys->waveformat.nSamplesPerSec *
p_aout->output.p_sys->waveformat.nBlockAlign;
/* Open the device */
result = waveOutOpen( &p_aout->p_sys->h_waveout, WAVE_MAPPER,
&p_aout->p_sys->waveformat,
0 /*callback*/, 0 /*callback data*/, CALLBACK_NULL );
result = waveOutOpen( &p_aout->output.p_sys->h_waveout, WAVE_MAPPER,
&p_aout->output.p_sys->waveformat,
(DWORD_PTR)WaveOutCallback, (DWORD_PTR)p_aout,
CALLBACK_FUNCTION );
if( result == WAVERR_BADFORMAT )
{
msg_Err( p_aout, "waveOutOpen failed WAVERR_BADFORMAT" );
return( 1 );
}
if( result != MMSYSERR_NOERROR )
{
msg_Err( p_aout, "waveOutOpen failed" );
return( 1 );
return 1;
}
return 0;
}
/*****************************************************************************
* 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 )
{
MMRESULT result;
/* Prepare the buffer */
if( p_buffer != NULL )
p_waveheader->lpData = p_buffer->p_buffer;
else
/* Use silence buffer instead */
p_waveheader->lpData = p_aout->output.p_sys->p_silence_buffer;
p_waveheader->dwUser = (DWORD_PTR)p_buffer;
p_waveheader->dwBufferLength = p_aout->output.p_sys->i_buffer_size;
p_waveheader->dwFlags = 0;
result = waveOutPrepareHeader( h_waveout, p_waveheader, sizeof(WAVEHDR) );
if( result != MMSYSERR_NOERROR )
{
msg_Err( p_aout, "waveOutPrepareHeader failed" );
return 1;
}
/* Send the buffer to the waveOut queue */
result = waveOutWrite( h_waveout, p_waveheader, sizeof(WAVEHDR) );
if( result != MMSYSERR_NOERROR )
{
msg_Err( p_aout, "waveOutWrite failed" );
return 1;
}
return( 0 );
return 0;
}
/*****************************************************************************
* 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 )
{
aout_instance_t * p_aout = (aout_instance_t *)_p_aout;
WAVEHDR *p_waveheader = (WAVEHDR *)dwParam1;
aout_buffer_t * p_buffer;
if( uMsg != WOM_DONE ) return;
/* Unprepare and free the buffer which has just been played */
waveOutUnprepareHeader( h_waveout, p_waveheader, sizeof(WAVEHDR) );
if( p_waveheader->dwUser )
aout_BufferFree( (aout_buffer_t *)p_waveheader->dwUser );
/* FIXME : take into account WaveOut latency instead of mdate() */
p_buffer = aout_OutputNextBuffer( p_aout, mdate() );
PlayWaveOut( p_aout, h_waveout, p_waveheader, p_buffer );
}
......@@ -2,7 +2,7 @@
* aout.c: Windows DirectX audio output method
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: aout.c,v 1.1 2002/08/04 17:23:43 sam Exp $
* $Id: aout.c,v 1.2 2002/08/10 18:17:06 gbazin Exp $
*
* Authors: Gildas Bazin <gbazin@netcourrier.com>
*
......@@ -32,10 +32,13 @@
#include <vlc/vlc.h>
#include <vlc/aout.h>
#include "aout_internal.h"
#include <mmsystem.h>
#include <dsound.h>
#define FRAME_SIZE 2048 /* The size is in samples, not in bytes */
/*****************************************************************************
* DirectSound GUIDs.
* Defining them here allows us to get rid of the dxguid library during
......@@ -51,8 +54,9 @@ typedef struct notification_thread_t
{
VLC_COMMON_MEMBERS
aout_thread_t * p_aout;
aout_instance_t * p_aout;
DSBPOSITIONNOTIFY p_events[2]; /* play notification events */
int i_buffer_size; /* Size in bytes of one frame */
} notification_thread_t;
......@@ -78,29 +82,27 @@ struct aout_sys_t
HINSTANCE hdsound_dll; /* handle of the opened dsound dll */
long l_buffer_size; /* secondary sound buffer size */
long l_write_position; /* next write position for the buffer */
volatile vlc_bool_t b_buffer_underflown; /* buffer underflow detection */
volatile long l_data_played_from_beginning; /* for underflow detection */
volatile long l_data_written_from_beginning; /* for underflow detection */
vlc_mutex_t buffer_lock; /* audio buffer lock */
notification_thread_t * p_notif; /* DirectSoundThread id */
};
/*****************************************************************************
* Prototypes.
*****************************************************************************/
void E_(CloseAudio) ( vlc_object_t *p_this );
/*****************************************************************************
* Local prototypes.
*****************************************************************************/
static int SetFormat ( aout_thread_t * );
static int GetBufInfo ( aout_thread_t *, int );
static void Play ( aout_thread_t *, byte_t *, int );
static int SetFormat ( aout_instance_t * );
static void Play ( aout_instance_t *, aout_buffer_t * );
/* local functions */
static int DirectxCreateSecondaryBuffer ( aout_thread_t * );
static void DirectxDestroySecondaryBuffer( aout_thread_t * );
static int DirectxInitDSound ( aout_thread_t * );
static int DirectxCreateSecondaryBuffer ( aout_instance_t * );
static void DirectxDestroySecondaryBuffer( aout_instance_t * );
static int DirectxInitDSound ( aout_instance_t * );
static void DirectSoundThread ( notification_thread_t * );
/*****************************************************************************
......@@ -110,39 +112,36 @@ static void DirectSoundThread ( notification_thread_t * );
*****************************************************************************/
int E_(OpenAudio) ( vlc_object_t *p_this )
{
aout_thread_t * p_aout = (aout_thread_t *)p_this;
aout_instance_t * p_aout = (aout_instance_t *)p_this;
HRESULT dsresult;
DSBUFFERDESC dsbuffer_desc;
msg_Dbg( p_aout, "Open" );
/* Allocate structure */
p_aout->p_sys = malloc( sizeof( aout_sys_t ) );
if( p_aout->p_sys == NULL )
p_aout->output.p_sys = malloc( sizeof( aout_sys_t ) );
if( p_aout->output.p_sys == NULL )
{
msg_Err( p_aout, "out of memory" );
return( 1 );
return 1;
}
/* Initialize some variables */
p_aout->p_sys->p_dsobject = NULL;
p_aout->p_sys->p_dsbuffer_primary = NULL;
p_aout->p_sys->p_dsbuffer = NULL;
p_aout->p_sys->p_dsnotify = NULL;
p_aout->p_sys->l_data_written_from_beginning = 0;
p_aout->p_sys->l_data_played_from_beginning = 0;
vlc_mutex_init( p_aout, &p_aout->p_sys->buffer_lock );
p_aout->pf_setformat = SetFormat;
p_aout->pf_getbufinfo = GetBufInfo;
p_aout->pf_play = Play;
p_aout->output.p_sys->p_dsobject = NULL;
p_aout->output.p_sys->p_dsbuffer_primary = NULL;
p_aout->output.p_sys->p_dsbuffer = NULL;
p_aout->output.p_sys->p_dsnotify = NULL;
p_aout->output.p_sys->p_notif = NULL;
vlc_mutex_init( p_aout, &p_aout->output.p_sys->buffer_lock );
p_aout->output.pf_setformat = SetFormat;
p_aout->output.pf_play = Play;
/* Initialise DirectSound */
if( DirectxInitDSound( p_aout ) )
{
msg_Warn( p_aout, "cannot initialize DirectSound" );
return( 1 );
msg_Err( p_aout, "cannot initialize DirectSound" );
goto error;
}
/* Obtain (not create) Direct Sound primary buffer */
......@@ -150,43 +149,45 @@ int E_(OpenAudio) ( vlc_object_t *p_this )
dsbuffer_desc.dwSize = sizeof(DSBUFFERDESC);
dsbuffer_desc.dwFlags = DSBCAPS_PRIMARYBUFFER;
msg_Warn( p_aout, "create direct sound primary buffer" );
dsresult = IDirectSound_CreateSoundBuffer(p_aout->p_sys->p_dsobject,
&dsbuffer_desc,
&p_aout->p_sys->p_dsbuffer_primary,
NULL);
dsresult = IDirectSound_CreateSoundBuffer(p_aout->output.p_sys->p_dsobject,
&dsbuffer_desc,
&p_aout->output.p_sys->p_dsbuffer_primary,
NULL);
if( dsresult != DS_OK )
{
msg_Warn( p_aout, "cannot create direct sound primary buffer" );
IDirectSound_Release( p_aout->p_sys->p_dsobject );
p_aout->p_sys->p_dsobject = NULL;
p_aout->p_sys->p_dsbuffer_primary = NULL;
return( 1 );
msg_Err( p_aout, "cannot create direct sound primary buffer" );
goto error;
}
/* Now we need to setup DirectSound play notification */
p_aout->output.p_sys->p_notif =
vlc_object_create( p_aout, sizeof(notification_thread_t) );
p_aout->output.p_sys->p_notif->p_aout = p_aout;
/* first we need to create the notification events */
p_aout->p_sys->p_notif->p_events[0].hEventNotify =
p_aout->output.p_sys->p_notif->p_events[0].hEventNotify =
CreateEvent( NULL, FALSE, FALSE, NULL );
p_aout->p_sys->p_notif->p_events[1].hEventNotify =
p_aout->output.p_sys->p_notif->p_events[1].hEventNotify =
CreateEvent( NULL, FALSE, FALSE, NULL );
/* then launch the notification thread */
msg_Dbg( p_aout, "creating DirectSoundThread" );