Commit 595d7684 authored by Gildas Bazin's avatar Gildas Bazin

* Added a new very simple audio plugin for Win32. This plugin uses the
    waveOut API which is a lot easier to use for streaming stuff than
    directsound. (you don't have to take care of underflows anymore
    because it doesn't use circular buffers).
    If you are having a lot of underflows, this plugin is currently
    better adapted than the directx plugin.

* Moved some initialization stuff in audio_out.c so we can now the
    caracteristics of the audio stream before calling aout_Open().
parent 8c0d4cd7
......@@ -20,6 +20,7 @@ PLUGINS_DIR := ac3_adec \
beos \
chroma \
directx \
downmix \
dsp \
dummy \
dvd \
......@@ -30,7 +31,6 @@ PLUGINS_DIR := ac3_adec \
ggi \
glide \
gtk \
downmix \
idct \
imdct \
kde \
......@@ -65,6 +65,9 @@ PLUGINS_TARGETS := ac3_adec/ac3_adec \
chroma/chroma_i420_ymga \
chroma/chroma_i420_ymga_mmx \
directx/directx \
downmix/downmix \
downmix/downmixsse \
downmix/downmix3dn \
dsp/dsp \
dummy/dummy \
dummy/null \
......@@ -81,9 +84,6 @@ PLUGINS_TARGETS := ac3_adec/ac3_adec \
glide/glide \
gtk/gnome \
gtk/gtk \
downmix/downmix \
downmix/downmixsse \
downmix/downmix3dn \
idct/idct \
idct/idctclassic \
idct/idctmmx \
......@@ -118,6 +118,7 @@ PLUGINS_TARGETS := ac3_adec/ac3_adec \
text/ncurses \
text/rc \
vcd/vcd \
win32/waveout \
win32/win32 \
x11/x11 \
x11/xvideo
......
......@@ -95,6 +95,7 @@ LIB_QNX = @LIB_QNX@
LIB_QT = @LIB_QT@
LIB_RC = @LIB_RC@
LIB_SDL = @LIB_SDL@
LIB_WAVEOUT = @LIB_WAVEOUT@
LIB_WIN32 = @LIB_WIN32@
LIB_X11 = @LIB_X11@
LIB_XVIDEO = @LIB_XVIDEO@
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -1136,13 +1136,13 @@ dnl
dnl Windows DirectX module
dnl
AC_ARG_ENABLE(directx,
[ --disable-directx Windows DirectX support (default enabled on WIN32)])
[ --disable-directx Win32 DirectX support (default enabled on Win32)])
if test "x$enableval" != "xno"
then
if test $SYS = mingw32
then
AC_ARG_WITH(directx-path,
[ --with-directx-path=path Windows DirectX headers and libraries])
[ --with-directx-path=path Win32 DirectX headers and libraries])
if test "x$with_directx_path" = "x"
then
AC_CHECK_HEADERS(directx.h,
......@@ -1164,11 +1164,22 @@ then
fi
fi
dnl
dnl win32 waveOut plugin
dnl
AC_ARG_ENABLE(waveout,
[ --disable-waveout Win32 waveOut module (default enabled on Win32)])
if ((test "x$enableval" != "xno") && (test $SYS = mingw32))
then
PLUGINS="${PLUGINS} waveout"
LIB_WAVEOUT="-lwinmm"
fi
dnl
dnl Windows MFC interface module
dnl
AC_ARG_ENABLE(win32,
[ --enable-win32 Windows DirectX support (default disabled)],
[ --enable-win32 Win32 interface support (default disabled)],
[ if test "x$enableval" != "xno"
then
PLUGINS="${PLUGINS} win32"
......@@ -1482,6 +1493,7 @@ AC_SUBST(LIB_QNX)
AC_SUBST(LIB_QT)
AC_SUBST(LIB_RC)
AC_SUBST(LIB_SDL)
AC_SUBST(LIB_WAVEOUT)
AC_SUBST(LIB_WIN32)
AC_SUBST(LIB_X11)
AC_SUBST(LIB_XVIDEO)
......
win32_SRC = win32.cpp
waveout_SOURCES = waveout.c aout_waveout.c
/*****************************************************************************
* aout_waveout.c: Windows waveOut audio output method
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: aout_waveout.c,v 1.1 2002/01/25 06:43:34 gbazin Exp $
*
* Authors: Gildas Bazin <gbazin@netcourrier.com>
*
* 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
* (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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <errno.h> /* ENOMEM */
#include <fcntl.h> /* open(), O_WRONLY */
#include <string.h> /* strerror() */
#include <stdio.h> /* "intf_msg.h" */
#include <stdlib.h> /* calloc(), malloc(), free() */
#include <videolan/vlc.h>
#include <mmsystem.h>
#include "audio_output.h" /* aout_thread_t */
#define NUMBUF 3 /* We use triple buffering to be on the safe side */
/*****************************************************************************
* aout_sys_t: waveOut audio output method descriptor
*****************************************************************************
* This structure is part of the audio output thread descriptor.
* It describes the waveOut specific properties of an audio device.
*****************************************************************************/
typedef struct aout_sys_s
{
HWAVEOUT h_waveout; /* handle to waveout instance */
WAVEFORMATEX waveformat; /* Audio format */
WAVEHDR waveheader[NUMBUF];
int i_current_buffer;
DWORD dw_counter; /* Number of bytes played since beginning */
} aout_sys_t;
/*****************************************************************************
* Local prototypes.
*****************************************************************************/
static int aout_Probe ( probedata_t *p_data );
static int aout_Open ( aout_thread_t *p_aout );
static int aout_SetFormat ( aout_thread_t *p_aout );
static long aout_GetBufInfo ( aout_thread_t *p_aout, long l_buffer_info );
static void aout_Play ( aout_thread_t *p_aout,
byte_t *buffer, int i_size );
static void aout_Close ( aout_thread_t *p_aout );
/* local functions */
static int OpenWaveOutDevice( aout_thread_t *p_aout );
/*****************************************************************************
* Functions exported as capabilities. They are declared as static so that
* we don't pollute the namespace too much.
*****************************************************************************/
void _M( aout_getfunctions )( function_list_t * p_function_list )
{
p_function_list->pf_probe = aout_Probe;
p_function_list->functions.aout.pf_open = aout_Open;
p_function_list->functions.aout.pf_setformat = aout_SetFormat;
p_function_list->functions.aout.pf_getbufinfo = aout_GetBufInfo;
p_function_list->functions.aout.pf_play = aout_Play;
p_function_list->functions.aout.pf_close = aout_Close;
}
/*****************************************************************************
* aout_Probe: probe the audio device and return a score
*****************************************************************************
* This function tries to probe for a waveOut sound device and returns a
* score to the plugin manager so it can select the best plugin.
*****************************************************************************/
static int aout_Probe( probedata_t *p_data )
{
HWAVEOUT h_waveout;
WAVEFORMATEX waveformat;
MMRESULT result;
/* Set a common sound format */
waveformat.wFormatTag = WAVE_FORMAT_PCM;
waveformat.nChannels = 2;
waveformat.nSamplesPerSec = 44100;
waveformat.wBitsPerSample = 16;
waveformat.nBlockAlign = waveformat.wBitsPerSample / 8 * 2;
waveformat.nAvgBytesPerSec = waveformat.nSamplesPerSec *
waveformat.nBlockAlign;
/* Open the device */
result = waveOutOpen( &h_waveout, WAVE_MAPPER, &waveformat,
0 /*callback*/, 0 /*callback data*/, CALLBACK_NULL );
if( result != MMSYSERR_NOERROR )
{
return( 0 );
}
waveOutClose( h_waveout );
return( 150 );
}
/*****************************************************************************
* aout_Open: open the audio device
*****************************************************************************
* This function opens and setups Win32 waveOut
*****************************************************************************/
static int aout_Open( aout_thread_t *p_aout )
{
int i;
intf_WarnMsg( 3, "aout: waveOut aout_Open ");
/* Allocate structure */
p_aout->p_sys = malloc( sizeof( aout_sys_t ) );
if( p_aout->p_sys == NULL )
{
intf_ErrMsg( "aout error: %s", strerror(ENOMEM) );
return( 1 );
}
/* 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->i_latency = 0;
p_aout->psz_device = 0;
p_aout->i_format = AOUT_FORMAT_DEFAULT;
return OpenWaveOutDevice( p_aout );
}
/*****************************************************************************
* aout_SetFormat: reset the audio device and sets its format
*****************************************************************************
* This functions set a new audio format.
* For this we need to close the current device and create another
* one with the desired format.
*****************************************************************************/
static int aout_SetFormat( aout_thread_t *p_aout )
{
intf_WarnMsg( 3, "aout: WaveOut aout_SetFormat ");
/* Check if the format has changed */
if( (p_aout->p_sys->waveformat.nChannels != p_aout->i_channels) ||
(p_aout->p_sys->waveformat.nSamplesPerSec != p_aout->l_rate) )
{
if( waveOutClose( p_aout->p_sys->h_waveout ) == MMSYSERR_NOERROR )
{
intf_ErrMsg( "aout error: waveOutClose failed" );
}
return OpenWaveOutDevice( p_aout );
}
return 0;
}
/*****************************************************************************
* aout_GetBufInfo: buffer status query
*****************************************************************************
* returns the number of bytes in the audio buffer that have not yet been
* sent to the sound device.
*****************************************************************************/
static long aout_GetBufInfo( aout_thread_t *p_aout, long l_buffer_limit )
{
MMTIME mmtime;
mmtime.wType = TIME_BYTES;
if( (waveOutGetPosition(p_aout->p_sys->h_waveout, &mmtime, sizeof(MMTIME)))
!= MMSYSERR_NOERROR || (mmtime.wType != TIME_BYTES) )
{
intf_WarnMsg( 3, "aout: aout_GetBufInfo waveOutGetPosition failed");
return l_buffer_limit;
}
#if 0
intf_WarnMsg( 3, "aout: waveOut aout_GetBufInfo: %i",
p_aout->p_sys->dw_counter - mmtime.u.cb );
#endif
return (p_aout->p_sys->dw_counter - mmtime.u.cb);
}
/*****************************************************************************
* aout_Play: play a sound buffer
*****************************************************************************
* This function writes a buffer of i_length bytes
*****************************************************************************/
static void aout_Play( aout_thread_t *p_aout, byte_t *p_buffer, int i_size )
{
MMRESULT result;
int current_buffer = p_aout->p_sys->i_current_buffer;
p_aout->p_sys->i_current_buffer = (current_buffer + 1) % NUMBUF;
/* 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 )
{
intf_ErrMsg( "aout error: aou_Play couldn't alloc 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 )
{
intf_ErrMsg( "aout error: waveOutPrepareHeader failed" );
return;
}
/* Send the buffer the waveOut queue */
FAST_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 )
{
intf_ErrMsg( "aout error: waveOutWrite failed" );
return;
}
/* keep track of number of bytes played */
p_aout->p_sys->dw_counter += i_size;
}
/*****************************************************************************
* aout_Close: close the audio device
*****************************************************************************/
static void aout_Close( aout_thread_t *p_aout )
{
int i;
intf_WarnMsg( 3, "aout: waveOut aout_Close ");
/* Close the device */
if( waveOutClose( p_aout->p_sys->h_waveout ) == MMSYSERR_NOERROR )
{
intf_ErrMsg( "aout error: waveOutClose failed" );
}
/* Deallocate memory */
for( i=0; i<NUMBUF; i++ )
free( p_aout->p_sys->waveheader[i].lpData );
if( p_aout->p_sys != NULL )
{
free( p_aout->p_sys );
p_aout->p_sys = NULL;
}
}
/*****************************************************************************
* OpenWaveOutDevice: open the sound device
****************************************************************************/
static int OpenWaveOutDevice( aout_thread_t *p_aout )
{
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->l_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;
/* 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 );
if( result != MMSYSERR_NOERROR )
{
intf_ErrMsg( "aout error: waveOutOpen failed" );
return( 1 );
}
return( 0 );
}
/*****************************************************************************
* waveout.c : Windows waveOut plugin for vlc
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: waveout.c,v 1.1 2002/01/25 06:43:34 gbazin Exp $
*
* Authors: Gildas Bazin <gbazin@netcourrier.com>
*
* 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
* (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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <stdlib.h> /* malloc(), free() */
#include <string.h>
#include <videolan/vlc.h>
#include "audio_output.h"
/*****************************************************************************
* Capabilities defined in the other files.
*****************************************************************************/
void _M( aout_getfunctions )( function_list_t * p_function_list );
/*****************************************************************************
* Building configuration tree
*****************************************************************************/
MODULE_CONFIG_START
ADD_WINDOW( "Configuration for Windows waveOut module" )
ADD_COMMENT( "For now, the Windows WaveOut module cannot be configured" )
MODULE_CONFIG_STOP
MODULE_INIT_START
SET_DESCRIPTION( "Win32 waveOut extension module" )
ADD_CAPABILITY( AOUT, 150 )
ADD_SHORTCUT( "waveout" )
MODULE_INIT_STOP
MODULE_ACTIVATE_START
_M( aout_getfunctions )( &p_module->p_functions->aout );
MODULE_ACTIVATE_STOP
MODULE_DEACTIVATE_START
MODULE_DEACTIVATE_STOP
......@@ -2,7 +2,7 @@
* audio_output.c : audio output thread
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: audio_output.c,v 1.73 2002/01/15 11:51:11 asmax Exp $
* $Id: audio_output.c,v 1.74 2002/01/25 06:43:34 gbazin Exp $
*
* Authors: Michel Kaempf <maxx@via.ecp.fr>
* Cyril Deguet <asmax@via.ecp.fr>
......@@ -92,6 +92,28 @@ aout_thread_t *aout_CreateThread( int *pi_status, int i_channels, long l_rate )
return( NULL );
}
p_aout->l_rate = l_rate;
p_aout->i_channels = i_channels;
/* special setting for ac3 pass-through mode */
/* FIXME is it necessary ? (cf ac3_adec.c) */
if( main_GetIntVariable( AOUT_SPDIF_VAR, 0 ) && p_main->b_ac3 )
{
intf_WarnMsg( 4, "aout info: setting ac3 spdif" );
p_aout->i_format = AOUT_FMT_AC3;
p_aout->l_rate = 48000;
}
if( p_aout->l_rate == 0 )
{
intf_ErrMsg( "aout error: null sample rate" );
free( p_aout );
return( NULL );
}
/* FIXME: only works for i_channels == 1 or 2 ?? */
p_aout->b_stereo = ( p_aout->i_channels == 2 ) ? 1 : 0;
/* Choose the best module */
p_aout->p_module = module_Need( MODULE_CAPABILITY_AOUT,
main_GetPszVariable( AOUT_METHOD_VAR, NULL ),
......@@ -122,30 +144,6 @@ aout_thread_t *aout_CreateThread( int *pi_status, int i_channels, long l_rate )
return( NULL );
}
p_aout->l_rate = l_rate;
p_aout->i_channels = i_channels;
/* special setting for ac3 pass-through mode */
/* FIXME is it necessary ? (cf ac3_adec.c) */
if( main_GetIntVariable( AOUT_SPDIF_VAR, 0 ) && p_main->b_ac3 )
{
intf_WarnMsg( 4, "aout info: setting ac3 spdif" );
p_aout->i_format = AOUT_FMT_AC3;
p_aout->l_rate = 48000;
}
if( p_aout->l_rate == 0 )
{
intf_ErrMsg( "aout error: null sample rate" );
p_aout->pf_close( p_aout );
module_Unneed( p_aout->p_module );
free( p_aout );
return( NULL );
}
/* FIXME: only works for i_channels == 1 or 2 ?? */
p_aout->b_stereo = ( p_aout->i_channels == 2 ) ? 1 : 0;
if ( p_aout->pf_setformat( p_aout ) )
{
p_aout->pf_close( p_aout );
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment