[vlc-devel] [PATCH] Remove aout_Packet from directsound audio output
Denis Charmet
typx at dinauz.org
Mon Feb 4 22:59:37 CET 2013
---
modules/audio_output/directx.c | 415 +++++++++++++++++-----------------------
1 file changed, 179 insertions(+), 236 deletions(-)
diff --git a/modules/audio_output/directx.c b/modules/audio_output/directx.c
index efd9a50..c45eb95 100644
--- a/modules/audio_output/directx.c
+++ b/modules/audio_output/directx.c
@@ -35,25 +35,10 @@
#include <vlc_plugin.h>
#include <vlc_aout.h>
#include <vlc_charset.h>
-#include <vlc_atomic.h>
#include "windows_audio_common.h"
-/*****************************************************************************
- * notification_thread_t: DirectX event thread
- *****************************************************************************/
-typedef struct notification_thread_t
-{
- int i_frame_size; /* size in bytes of one frame */
- int i_write_slot; /* current write position in our circular buffer */
-
- mtime_t start_date;
- HANDLE event;
-
- vlc_thread_t thread;
- vlc_atomic_t abort;
-
-} notification_thread_t;
+#define DS_BUF_SIZE (1024*1024)
/*****************************************************************************
* aout_sys_t: directx audio output method descriptor
@@ -63,30 +48,33 @@ typedef struct notification_thread_t
*****************************************************************************/
struct aout_sys_t
{
- aout_packet_t packet;
- HINSTANCE hdsound_dll; /* handle of the opened dsound dll */
+ HINSTANCE hdsound_dll; /* handle of the opened dsound dll */
- LPDIRECTSOUND p_dsobject; /* main Direct Sound object */
+ LPDIRECTSOUND p_dsobject; /* main Direct Sound object */
LPDIRECTSOUNDBUFFER p_dsbuffer; /* the sound buffer we use (direct sound
* takes care of mixing all the
* secondary buffers into the primary) */
+
+ LPDIRECTSOUNDNOTIFY p_notify;
+ HANDLE hnotify_evt;
struct
{
- LONG volume;
+ float volume;
LONG mb;
bool mute;
} volume;
- notification_thread_t notif; /* DirectSoundThread id */
-
- int i_frame_size; /* Size in bytes of one frame */
+ int i_bytes_per_sample; /* Size in bytes of one frame */
+ int i_rate; /* Sample rate */
- int i_speaker_setup; /* Speaker setup override */
+ int i_speaker_setup; /* Speaker setup override */
- uint8_t chans_to_reorder; /* do we need channel reordering */
+ uint8_t chans_to_reorder; /* do we need channel reordering */
uint8_t chan_table[AOUT_CHAN_MAX];
uint32_t i_channel_mask;
vlc_fourcc_t format;
+
+ size_t i_write;
};
/*****************************************************************************
@@ -95,18 +83,20 @@ struct aout_sys_t
static int Open( vlc_object_t * );
static void Close( vlc_object_t * );
static void Stop( audio_output_t * );
-static void Play ( audio_output_t *, block_t * );
-static int VolumeSet ( audio_output_t *, float );
-static int MuteSet ( audio_output_t *, bool );
+static void Play( audio_output_t *, block_t * );
+static int VolumeSet( audio_output_t *, float );
+static int MuteSet( audio_output_t *, bool );
+static void Flush( audio_output_t *, bool );
+static void Pause( audio_output_t *, bool, mtime_t );
+static int TimeGet( audio_output_t *, mtime_t *);
/* local functions */
static void Probe( audio_output_t *, const audio_sample_format_t * );
static int InitDirectSound ( audio_output_t * );
-static int CreateDSBuffer ( audio_output_t *, int, int, int, int, int, bool );
+static int CreateDSBuffer ( audio_output_t *, int, int, int, int, bool );
static int CreateDSBufferPCM ( audio_output_t *, vlc_fourcc_t*, int, int, bool );
static void DestroyDSBuffer ( audio_output_t * );
-static void* DirectSoundThread( void * );
-static int FillBuffer ( audio_output_t *, int, block_t * );
+static int FillBuffer ( audio_output_t *, block_t * );
static int ReloadDirectXDevices( vlc_object_t *, const char *,
char ***, char *** );
@@ -145,7 +135,7 @@ vlc_module_begin ()
add_string( "directx-audio-speaker", "Windows default",
SPEAKER_TEXT, SPEAKER_LONGTEXT, true )
change_string_list( speaker_list, speaker_list )
- add_integer( "directx-volume", DSBVOLUME_MAX,
+ add_float( "directx-volume", 1.0f,
VOLUME_TEXT, VOLUME_LONGTEXT, true )
change_integer_range( DSBVOLUME_MIN, DSBVOLUME_MAX )
@@ -216,19 +206,15 @@ static int Start( audio_output_t *p_aout, audio_sample_format_t *restrict fmt )
/* Calculate the frame size in bytes */
fmt->i_bytes_per_frame = AOUT_SPDIF_SIZE;
fmt->i_frame_length = A52_FRAME_NB;
- p_aout->sys->i_frame_size = fmt->i_bytes_per_frame;
if( CreateDSBuffer( p_aout, VLC_CODEC_SPDIFL,
fmt->i_physical_channels,
- aout_FormatNbChannels( fmt ), fmt->i_rate,
- p_aout->sys->i_frame_size, false )
+ aout_FormatNbChannels( fmt ), fmt->i_rate, false )
!= VLC_SUCCESS )
{
msg_Err( p_aout, "cannot open directx audio device" );
goto error;
}
-
- aout_PacketInit( p_aout, &p_aout->sys->packet, A52_FRAME_NB, fmt );
}
else
{
@@ -254,37 +240,19 @@ static int Start( audio_output_t *p_aout, audio_sample_format_t *restrict fmt )
msg_Err( p_aout, "cannot open directx audio device" );
goto error;
}
-
- /* Calculate the frame size in bytes */
- aout_PacketInit( p_aout, &p_aout->sys->packet, fmt->i_rate / 20, fmt );
}
+ p_aout->sys->i_write = 0;
- /* Force volume update in thread. TODO: use session volume on Vista+ */
- p_aout->sys->volume.volume = p_aout->sys->volume.mb;
-
- /* Now we need to setup our DirectSound play notification structure */
- vlc_atomic_set(&p_aout->sys->notif.abort, 0);
- p_aout->sys->notif.event = CreateEvent( 0, FALSE, FALSE, 0 );
- if( unlikely(p_aout->sys->notif.event == NULL) )
- abort();
- p_aout->sys->notif.i_frame_size = p_aout->sys->i_frame_size;
+ /* Force volume update */
+ VolumeSet( p_aout, p_aout->sys->volume.volume );
+ MuteSet( p_aout, p_aout->sys->volume.mute );
/* then launch the notification thread */
- msg_Dbg( p_aout, "creating DirectSoundThread" );
- if( vlc_clone( &p_aout->sys->notif.thread, DirectSoundThread, p_aout,
- VLC_THREAD_PRIORITY_HIGHEST ) )
- {
- msg_Err( p_aout, "cannot create DirectSoundThread" );
- CloseHandle( p_aout->sys->notif.event );
- p_aout->sys->notif.event = NULL;
- aout_PacketDestroy( p_aout );
- goto error;
- }
-
- p_aout->time_get = aout_PacketTimeGet;
+ p_aout->time_get = TimeGet;
p_aout->play = Play;
- p_aout->pause = NULL;
- p_aout->flush = aout_PacketFlush;
+ p_aout->pause = Pause;
+ p_aout->flush = Flush;
+
return VLC_SUCCESS;
error:
@@ -479,8 +447,7 @@ static void Probe( audio_output_t * p_aout, const audio_sample_format_t *fmt )
{
if( CreateDSBuffer( p_aout, VLC_CODEC_SPDIFL,
fmt->i_physical_channels,
- aout_FormatNbChannels( fmt ), fmt->i_rate,
- AOUT_SPDIF_SIZE, true )
+ aout_FormatNbChannels( fmt ), fmt->i_rate, true )
== VLC_SUCCESS )
{
msg_Dbg( p_aout, "device supports A/52 over S/PDIF" );
@@ -509,28 +476,32 @@ static void Probe( audio_output_t * p_aout, const audio_sample_format_t *fmt )
* we know the first buffer has been put in the aout fifo and we also
* know its date.
*****************************************************************************/
+
static void Play( audio_output_t *p_aout, block_t *p_buffer )
{
- /* get the playing date of the first aout buffer */
- p_aout->sys->notif.start_date = p_buffer->i_pts;
-
- /* fill in the first samples (zeroes) */
- FillBuffer( p_aout, 0, NULL );
-
- /* wake up the audio output thread */
- SetEvent( p_aout->sys->notif.event );
-
- aout_PacketPlay( p_aout, p_buffer );
- p_aout->play = aout_PacketPlay;
+ if( FillBuffer( p_aout, p_buffer ) == VLC_SUCCESS )
+ {
+ /* start playing the buffer */
+ HRESULT dsresult = IDirectSoundBuffer_Play( p_aout->sys->p_dsbuffer,
+ 0, 0, DSBPLAY_LOOPING );
+ if( dsresult == DSERR_BUFFERLOST )
+ {
+ IDirectSoundBuffer_Restore( p_aout->sys->p_dsbuffer );
+ dsresult = IDirectSoundBuffer_Play( p_aout->sys->p_dsbuffer,
+ 0, 0, DSBPLAY_LOOPING );
+ }
+ if( dsresult != DS_OK )
+ msg_Err( p_aout, "cannot start playing buffer" );
+ }
}
-static int VolumeSet( audio_output_t *p_aout, float vol )
+static int VolumeSet( audio_output_t *p_aout, float volume )
{
aout_sys_t *sys = p_aout->sys;
int ret = 0;
/* Convert UI volume to linear factor (cube) */
- vol = vol * vol * vol;
+ float vol = volume * volume * volume;
/* millibels from linear amplification */
LONG mb = lroundf(2000.f * log10f(vol));
@@ -546,28 +517,31 @@ static int VolumeSet( audio_output_t *p_aout, float vol )
mb = DSBVOLUME_MIN;
sys->volume.mb = mb;
- if (!sys->volume.mute)
- InterlockedExchange(&sys->volume.volume, mb);
-
+ sys->volume.volume = volume;
+ if( !sys->volume.mute && sys->p_dsbuffer &&
+ IDirectSoundBuffer_SetVolume( sys->p_dsbuffer, mb ) != DS_OK )
+ return -1;
/* Convert back to UI volume */
- vol = cbrtf(powf(10.f, ((float)mb) / 2000.f));
- aout_VolumeReport( p_aout, vol );
+ aout_VolumeReport( p_aout, volume );
if( var_InheritBool( p_aout, "volume-save" ) )
- config_PutInt( p_aout, "directx-volume", mb );
+ config_PutFloat( p_aout, "directx-volume", volume );
return ret;
}
static int MuteSet( audio_output_t *p_aout, bool mute )
{
+ HRESULT res = DS_OK;
aout_sys_t *sys = p_aout->sys;
sys->volume.mute = mute;
- InterlockedExchange(&sys->volume.volume,
- mute ? DSBVOLUME_MIN : sys->volume.mb);
+
+ if( sys->p_dsbuffer )
+ res = IDirectSoundBuffer_SetVolume( sys->p_dsbuffer,
+ mute? DSBVOLUME_MIN : sys->volume.mb );
aout_MuteReport( p_aout, mute );
- return 0;
+ return (res != DS_OK);
}
/*****************************************************************************
@@ -576,27 +550,19 @@ static int MuteSet( audio_output_t *p_aout, bool mute )
static void Stop( audio_output_t *p_aout )
{
aout_sys_t *p_sys = p_aout->sys;
-
msg_Dbg( p_aout, "closing audio device" );
- /* kill the position notification thread, if any */
- if( p_sys->notif.event != NULL )
- {
- vlc_atomic_set(&p_aout->sys->notif.abort, 1);
- /* wake up the audio thread if needed */
- if( p_aout->play == Play )
- SetEvent( p_sys->notif.event );
-
- vlc_join( p_sys->notif.thread, NULL );
- CloseHandle( p_sys->notif.event );
- aout_PacketDestroy( p_aout );
- }
+ if( p_sys->p_notify )
+ IDirectSoundNotify_Release(p_sys->p_notify );
+ p_sys->p_notify = NULL;
+ IDirectSoundBuffer_Stop( p_sys->p_dsbuffer );
/* release the secondary buffer */
DestroyDSBuffer( p_aout );
/* finally release the DirectSound object */
- if( p_sys->p_dsobject ) IDirectSound_Release( p_sys->p_dsobject );
+ if( p_sys->p_dsobject )
+ IDirectSound_Release( p_sys->p_dsobject );
}
/*****************************************************************************
@@ -675,7 +641,7 @@ static int InitDirectSound( audio_output_t *p_aout )
*****************************************************************************/
static int CreateDSBuffer( audio_output_t *p_aout, int i_format,
int i_channels, int i_nb_channels, int i_rate,
- int i_bytes_per_frame, bool b_probe )
+ bool b_probe )
{
WAVEFORMATEXTENSIBLE waveformat;
DSBUFFERDESC dsbdesc;
@@ -723,14 +689,16 @@ static int CreateDSBuffer( audio_output_t *p_aout, int i_format,
waveformat.Format.nAvgBytesPerSec =
waveformat.Format.nSamplesPerSec * waveformat.Format.nBlockAlign;
+ p_aout->sys->i_bytes_per_sample = waveformat.Format.nBlockAlign;
p_aout->sys->format = i_format;
/* Then fill in the direct sound descriptor */
memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
dsbdesc.dwSize = sizeof(DSBUFFERDESC);
- dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2/* Better position accuracy */
- | DSBCAPS_GLOBALFOCUS /* Allows background playing */
- | DSBCAPS_CTRLVOLUME; /* Allows volume control */
+ dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 /* Better position accuracy */
+ | DSBCAPS_GLOBALFOCUS /* Allows background playing */
+ | DSBCAPS_CTRLVOLUME /* Allows volume control */
+ | DSBCAPS_CTRLPOSITIONNOTIFY; /* Allow position notifications */
/* Only use the new WAVE_FORMAT_EXTENSIBLE format for multichannel audio */
if( i_nb_channels <= 2 )
@@ -747,7 +715,7 @@ static int CreateDSBuffer( audio_output_t *p_aout, int i_format,
dsbdesc.dwFlags |= DSBCAPS_LOCHARDWARE;
}
- dsbdesc.dwBufferBytes = FRAMES_NUM * i_bytes_per_frame; /* buffer size */
+ dsbdesc.dwBufferBytes = DS_BUF_SIZE; /* buffer size */
dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&waveformat;
if FAILED( IDirectSound_CreateSoundBuffer(
@@ -781,7 +749,7 @@ static int CreateDSBuffer( audio_output_t *p_aout, int i_format,
return VLC_SUCCESS;
}
- p_aout->sys->i_frame_size = i_bytes_per_frame;
+ p_aout->sys->i_rate = i_rate;
p_aout->sys->i_channel_mask = waveformat.dwChannelMask;
p_aout->sys->chans_to_reorder =
aout_CheckChannelReorder( pi_channels_in, pi_channels_out,
@@ -792,6 +760,18 @@ static int CreateDSBuffer( audio_output_t *p_aout, int i_format,
msg_Dbg( p_aout, "channel reordering needed" );
}
+ if( IDirectSoundBuffer_QueryInterface( p_aout->sys->p_dsbuffer,
+ &IID_IDirectSoundNotify,
+ (void **) &p_aout->sys->p_notify )
+ != DS_OK )
+ {
+
+ msg_Err(p_aout, "Couldn't query IDirectSoundNotify");
+ p_aout->sys->p_notify = NULL;
+ }
+
+ FillBuffer(p_aout,NULL);
+
return VLC_SUCCESS;
}
@@ -810,13 +790,11 @@ static int CreateDSBufferPCM( audio_output_t *p_aout, vlc_fourcc_t *i_format,
if( !var_GetBool( p_aout, "directx-audio-float32" ) ||
i_nb_channels > 2 ||
CreateDSBuffer( p_aout, VLC_CODEC_FL32,
- i_channels, i_nb_channels, i_rate,
- (i_rate / 20) * 4 * i_nb_channels, b_probe )
+ i_channels, i_nb_channels, i_rate, b_probe )
!= VLC_SUCCESS )
{
if ( CreateDSBuffer( p_aout, VLC_CODEC_S16N,
- i_channels, i_nb_channels, i_rate,
- (i_rate / 20) * 2 * i_nb_channels, b_probe )
+ i_channels, i_nb_channels, i_rate, b_probe )
!= VLC_SUCCESS )
{
return VLC_EGENERIC;
@@ -853,31 +831,32 @@ static void DestroyDSBuffer( audio_output_t *p_aout )
*****************************************************************************
* Returns VLC_SUCCESS on success.
*****************************************************************************/
-static int FillBuffer( audio_output_t *p_aout, int i_frame, block_t *p_buffer )
+static int FillBuffer( audio_output_t *p_aout, block_t *p_buffer )
{
aout_sys_t *p_sys = p_aout->sys;
- notification_thread_t *p_notif = &p_sys->notif;
+
+ size_t towrite = (p_buffer)?p_buffer->i_buffer:DS_BUF_SIZE;
void *p_write_position, *p_wrap_around;
unsigned long l_bytes1, l_bytes2;
HRESULT dsresult;
/* Before copying anything, we have to lock the buffer */
dsresult = IDirectSoundBuffer_Lock(
- p_sys->p_dsbuffer, /* DS buffer */
- i_frame * p_notif->i_frame_size, /* Start offset */
- p_notif->i_frame_size, /* Number of bytes */
- &p_write_position, /* Address of lock start */
- &l_bytes1, /* Count of bytes locked before wrap around */
- &p_wrap_around, /* Buffer address (if wrap around) */
- &l_bytes2, /* Count of bytes after wrap around */
- 0 ); /* Flags */
+ p_sys->p_dsbuffer, /* DS buffer */
+ p_aout->sys->i_write, /* Start offset */
+ towrite, /* Number of bytes */
+ &p_write_position, /* Address of lock start */
+ &l_bytes1, /* Count of bytes locked before wrap around */
+ &p_wrap_around, /* Buffer address (if wrap around) */
+ &l_bytes2, /* Count of bytes after wrap around */
+ 0 ); /* Flags: DSBLOCK_FROMWRITECURSOR is buggy */
if( dsresult == DSERR_BUFFERLOST )
{
IDirectSoundBuffer_Restore( p_sys->p_dsbuffer );
dsresult = IDirectSoundBuffer_Lock(
p_sys->p_dsbuffer,
- i_frame * p_notif->i_frame_size,
- p_notif->i_frame_size,
+ p_aout->sys->i_write,
+ towrite,
&p_write_position,
&l_bytes1,
&p_wrap_around,
@@ -904,6 +883,8 @@ static int FillBuffer( audio_output_t *p_aout, int i_frame, block_t *p_buffer )
p_sys->format );
memcpy( p_write_position, p_buffer->p_buffer, l_bytes1 );
+ if( l_bytes1 < p_buffer->i_buffer)
+ memcpy(p_wrap_around, p_buffer->p_buffer + l_bytes1, l_bytes2);
block_Release( p_buffer );
}
@@ -911,117 +892,10 @@ static int FillBuffer( audio_output_t *p_aout, int i_frame, block_t *p_buffer )
IDirectSoundBuffer_Unlock( p_sys->p_dsbuffer, p_write_position, l_bytes1,
p_wrap_around, l_bytes2 );
- p_notif->i_write_slot = (i_frame + 1) % FRAMES_NUM;
- return VLC_SUCCESS;
-}
+ p_sys->i_write += towrite;
+ p_sys->i_write %= DS_BUF_SIZE;
-/*****************************************************************************
- * DirectSoundThread: this thread will capture play notification events.
- *****************************************************************************
- * We use this thread to emulate a callback mechanism. The thread probes for
- * event notification and fills up the DS secondary buffer when needed.
- *****************************************************************************/
-static void* DirectSoundThread( void *data )
-{
- audio_output_t *p_aout = (audio_output_t *)data;
- notification_thread_t *p_notif = &p_aout->sys->notif;
- mtime_t last_time;
-
- msg_Dbg( p_aout, "DirectSoundThread ready" );
-
- /* Wait here until Play() is called */
- WaitForSingleObject( p_notif->event, INFINITE );
-
- if( !vlc_atomic_get( &p_notif->abort) )
- {
- HRESULT dsresult;
- mwait( p_notif->start_date - AOUT_MAX_PTS_ADVANCE / 2 );
-
- /* start playing the buffer */
- dsresult = IDirectSoundBuffer_Play( p_aout->sys->p_dsbuffer,
- 0, /* Unused */
- 0, /* Unused */
- DSBPLAY_LOOPING ); /* Flags */
- if( dsresult == DSERR_BUFFERLOST )
- {
- IDirectSoundBuffer_Restore( p_aout->sys->p_dsbuffer );
- dsresult = IDirectSoundBuffer_Play(
- p_aout->sys->p_dsbuffer,
- 0, /* Unused */
- 0, /* Unused */
- DSBPLAY_LOOPING ); /* Flags */
- }
- if( dsresult != DS_OK )
- {
- msg_Err( p_aout, "cannot start playing buffer" );
- }
- }
- last_time = mdate();
-
- while( !vlc_atomic_get( &p_notif->abort ) )
- {
- DWORD l_read;
- int l_queued = 0, l_free_slots;
- unsigned i_frame_siz = p_aout->sys->packet.samples;
- mtime_t mtime = mdate();
- int i;
-
- /* Update volume if required */
- LONG volume = InterlockedExchange( &p_aout->sys->volume.volume, -1 );
- if( unlikely(volume != -1) )
- IDirectSoundBuffer_SetVolume( p_aout->sys->p_dsbuffer, volume );
-
- /*
- * Fill in as much audio data as we can in our circular buffer
- */
-
- /* Find out current play position */
- if FAILED( IDirectSoundBuffer_GetCurrentPosition(
- p_aout->sys->p_dsbuffer, &l_read, NULL ) )
- {
- msg_Err( p_aout, "GetCurrentPosition() failed!" );
- l_read = 0;
- }
-
- /* Detect underruns */
- if( l_queued && mtime - last_time >
- INT64_C(1000000) * l_queued / p_aout->sys->packet.format.i_rate )
- {
- msg_Dbg( p_aout, "detected underrun!" );
- }
- last_time = mtime;
-
- /* Try to fill in as many frame buffers as possible */
- l_read /= (p_aout->sys->packet.format.i_bytes_per_frame /
- p_aout->sys->packet.format.i_frame_length);
- l_queued = p_notif->i_write_slot * i_frame_siz - l_read;
- if( l_queued < 0 ) l_queued += (i_frame_siz * FRAMES_NUM);
- l_free_slots = (FRAMES_NUM * i_frame_siz - l_queued) / i_frame_siz;
-
- for( i = 0; i < l_free_slots; i++ )
- {
- block_t *p_buffer = aout_PacketNext( p_aout,
- mtime + INT64_C(1000000) * (i * i_frame_siz + l_queued) /
- p_aout->sys->packet.format.i_rate );
-
- /* If there is no audio data available and we have some buffered
- * already, then just wait for the next time */
- if( !p_buffer && (i || l_queued / i_frame_siz) ) break;
-
- if( FillBuffer( p_aout, p_notif->i_write_slot % FRAMES_NUM,
- p_buffer ) != VLC_SUCCESS ) break;
- }
-
- /* Sleep a reasonable amount of time */
- l_queued += (i * i_frame_siz);
- msleep( INT64_C(1000000) * l_queued / p_aout->sys->packet.format.i_rate / 2 );
- }
-
- /* make sure the buffer isn't playing */
- IDirectSoundBuffer_Stop( p_aout->sys->p_dsbuffer );
-
- msg_Dbg( p_aout, "DirectSoundThread exiting" );
- return NULL;
+ return VLC_SUCCESS;
}
typedef struct
@@ -1106,11 +980,19 @@ static int Open(vlc_object_t *obj)
aout->mute_set = MuteSet;
/* Volume */
- LONG mb = var_InheritInteger(aout, "directx-volume");
- sys->volume.mb = mb;
- aout_VolumeReport(aout, cbrtf(powf(10.f, ((float)mb) / 2000.f)));
+ sys->volume.volume = var_InheritFloat(aout, "directx-volume");
+ aout_VolumeReport(aout, sys->volume.volume );
MuteSet(aout, var_InheritBool(aout, "mute"));
+ sys->hnotify_evt = CreateEvent(NULL, FALSE, TRUE, NULL);
+ if( !sys->hnotify_evt )
+ {
+ msg_Err(aout, "cannot create Event");
+ FreeLibrary(sys->hdsound_dll);
+ free(sys);
+ return VLC_EGENERIC;
+ }
+
return VLC_SUCCESS;
}
@@ -1119,6 +1001,67 @@ static void Close(vlc_object_t *obj)
audio_output_t *aout = (audio_output_t *)obj;
aout_sys_t *sys = aout->sys;
+ CloseHandle(sys->hnotify_evt);
FreeLibrary(sys->hdsound_dll); /* free DSOUND.DLL */
free(sys);
}
+
+static void Flush ( audio_output_t * aout, bool drain )
+{
+ aout_sys_t *sys = aout->sys;
+ size_t read;
+ if( drain )
+ {
+ if( sys->p_notify )
+ {
+ DSBPOSITIONNOTIFY notif = {.dwOffset = aout->sys->i_write, .hEventNotify = sys->hnotify_evt } ;
+ if( IDirectSoundNotify_SetNotificationPositions( sys->p_notify, 1, ¬if ) == DS_OK )
+ {
+ WaitForSingleObject( sys->hnotify_evt, INFINITE );
+ IDirectSoundBuffer_Stop( aout->sys->p_dsbuffer );
+ }
+ }
+ else
+ while( IDirectSoundBuffer_GetCurrentPosition( aout->sys->p_dsbuffer,(LPDWORD) &read, NULL) == DS_OK )
+ {
+ read %= DS_BUF_SIZE;
+ if( read == aout->sys->i_write )
+ break;
+ msleep(10000);
+ }
+ }
+ else
+ {
+ IDirectSoundBuffer_Stop( aout->sys->p_dsbuffer );
+ IDirectSoundBuffer_SetCurrentPosition( aout->sys->p_dsbuffer,
+ aout->sys->i_write );
+ }
+}
+
+static void Pause( audio_output_t * aout, bool pause, mtime_t date )
+{
+ (void) date;
+ if( pause )
+ IDirectSoundBuffer_Stop( aout->sys->p_dsbuffer );
+ else
+ IDirectSoundBuffer_Play( aout->sys->p_dsbuffer, 0, 0, DSBPLAY_LOOPING );
+}
+
+
+static int TimeGet( audio_output_t * aout, mtime_t * delay )
+{
+ uint32_t read;
+ mtime_t size;
+
+ if( IDirectSoundBuffer_GetCurrentPosition( aout->sys->p_dsbuffer, (LPDWORD) &read, NULL) != DS_OK )
+ return 1;
+
+ read %= DS_BUF_SIZE;
+
+ size = (mtime_t)aout->sys->i_write - (mtime_t) read;
+ if( size < 0 )
+ size += DS_BUF_SIZE;
+
+ *delay = ( size / aout->sys->i_bytes_per_sample ) * CLOCK_FREQ / aout->sys->i_rate;
+ return 0;
+}
--
1.7.10.4
More information about the vlc-devel
mailing list