1
0
mirror of http://mpg123.de/trunk/.git synced 2025-10-25 04:37:34 +03:00

Fix an alsa (not just there, I guess) crash by making sure the ao->userptr and ao->fn get cleared after close in close_output.

Also removed direct uses of ao->close in mpg123.c and buffer.c .


git-svn-id: svn://scm.orgis.org/mpg123/trunk@1044 35dc7657-300d-0410-a2e5-dc2837fedb53
This commit is contained in:
thor
2007-10-24 16:13:46 +00:00
parent 168e6dddea
commit 72da73dbf3
6 changed files with 42 additions and 25 deletions

View File

@@ -329,12 +329,16 @@ void flush_output(int outmode, audio_output_t *ao, unsigned char *bytes, size_t
} }
} }
/* is this used? */
void close_output(int outmode, audio_output_t *ao) void close_output(int outmode, audio_output_t *ao)
{ {
switch(outmode) { switch(outmode) {
case DECODE_AUDIO: case DECODE_AUDIO:
ao->close(ao); ao->close(ao);
/* Module frees and closes its resources, but may not reset them. */
ao->userptr = NULL;
ao->fn = -1;
break; break;
case DECODE_WAV: case DECODE_WAV:
wav_close(); wav_close();
@@ -348,3 +352,14 @@ void close_output(int outmode, audio_output_t *ao)
} }
} }
/* Also for WAV decoding? */
int reset_output(audio_output_t *ao)
{
if(param.outmode == DECODE_AUDIO)
{
close_output(param.outmode, ao);
return ao->open(ao);
}
else return 0;
}

View File

@@ -78,7 +78,7 @@ const char* audio_encoding_name(const int encoding, const int longer);
int init_output(audio_output_t *ao, mpg123_handle *mh); int init_output(audio_output_t *ao, mpg123_handle *mh);
void flush_output(int outmode, audio_output_t *ao, unsigned char *bytes, size_t count); void flush_output(int outmode, audio_output_t *ao, unsigned char *bytes, size_t count);
void close_output(int mod, audio_output_t *ao ); void close_output(int mod, audio_output_t *ao );
int reset_output(audio_output_t *ao);
#endif #endif

View File

@@ -141,15 +141,12 @@ void buffer_loop(audio_output_t *ao, sigset_t *oldsigset)
*/ */
if (xf->wakeme[XF_WRITER]) if (xf->wakeme[XF_WRITER])
xfermem_putcmd(my_fd, XF_CMD_WAKEUP); xfermem_putcmd(my_fd, XF_CMD_WAKEUP);
if (param.outmode == DECODE_AUDIO) { ao->rate = xf->buf[0];
ao->close(ao); ao->channels = xf->buf[1];
ao->rate = xf->buf[0]; ao->format = xf->buf[2];
ao->channels = xf->buf[1]; if (reset_output(ao) < 0) {
ao->format = xf->buf[2]; error1("failed to reset audio: %s", strerror(errno));
if (ao->open(ao) < 0) { exit(1);
perror("audio");
exit(1);
}
} }
} }
if ( (bytes = xfermem_get_usedspace(xf)) < outburst ) { if ( (bytes = xfermem_get_usedspace(xf)) < outburst ) {

View File

@@ -419,9 +419,9 @@ static void reset_audio(void)
* the device's internal buffer before * the device's internal buffer before
* changing the sample rate. [OF] * changing the sample rate. [OF]
*/ */
ao->close(ao); if(reset_output(ao) < 0)
if (ao->open(ao) < 0) { {
error("failed to open audio device"); error1("failed to reset audio device: %s", strerror(errno));
safe_exit(1); safe_exit(1);
} }
} }

View File

@@ -21,6 +21,7 @@ output_dummy_la_LDFLAGS = -module -avoid-version
#pkglib_LTLIBRARIES += output_alib.la #pkglib_LTLIBRARIES += output_alib.la
#output_alib_la_SOURCES = alib.c #output_alib_la_SOURCES = alib.c
#output_alib_la_LDFLAGS = -module -avoid-version #output_alib_la_LDFLAGS = -module -avoid-version
#output_alib_la_CFLAGS= -I/opt/audio/include
#endif #endif
if HAVE_ALSA if HAVE_ALSA
@@ -90,7 +91,7 @@ if HAVE_PORTAUDIO
pkglib_LTLIBRARIES += output_portaudio.la pkglib_LTLIBRARIES += output_portaudio.la
output_portaudio_la_SOURCES = portaudio.c output_portaudio_la_SOURCES = portaudio.c
output_portaudio_la_LDFLAGS = -module -avoid-version output_portaudio_la_LDFLAGS = -module -avoid-version
output_portaudio_la_LIBADD = -lportaudio output_portaudio_la_LIBADD = -lportaudio @PORTAUDIO_EXTRA_LIB@
endif endif
if HAVE_PULSE if HAVE_PULSE
@@ -109,11 +110,12 @@ output_sdl_la_LDFLAGS = -module -avoid-version @SDL_LDFLAGS@
output_sdl_la_LIBADD = @SDL_LIBS@ output_sdl_la_LIBADD = @SDL_LIBS@
endif endif
#if HAVE_SGI if HAVE_SGI
#pkglib_LTLIBRARIES += output_sgi.la pkglib_LTLIBRARIES += output_sgi.la
#output_sgi_la_SOURCES = sgi.c output_sgi_la_SOURCES = sgi.c
#output_sgi_la_LDFLAGS = -module -avoid-version output_sgi_la_LDFLAGS = -module -avoid-version
#endif output_sgi_la_LIBADD = -laudio
endif
if HAVE_SUN if HAVE_SUN
pkglib_LTLIBRARIES += output_sun.la pkglib_LTLIBRARIES += output_sun.la
@@ -121,8 +123,9 @@ output_sun_la_SOURCES = sun.c
output_sun_la_LDFLAGS = -module -avoid-version output_sun_la_LDFLAGS = -module -avoid-version
endif endif
#if HAVE_WIN32 if HAVE_WIN32
#pkglib_LTLIBRARIES += output_win32.la pkglib_LTLIBRARIES += output_win32.la
#output_win32_la_SOURCES = win32.c output_win32_la_SOURCES = win32.c
#output_win32_la_LDFLAGS = -module -avoid-version output_win32_la_LDFLAGS = -module -avoid-version
#endif output_win32_la_LIBADD= -lwinmm
endif

View File

@@ -137,6 +137,7 @@ static int open_alsa(audio_output_t *ao)
{ {
const char *pcm_name; const char *pcm_name;
snd_pcm_t *pcm=NULL; snd_pcm_t *pcm=NULL;
debug1("open_alsa with %p", ao->userptr);
pcm_name = ao->device ? ao->device : "default"; pcm_name = ao->device ? ao->device : "default";
if (snd_pcm_open(&pcm, pcm_name, SND_PCM_STREAM_PLAYBACK, 0) < 0) { if (snd_pcm_open(&pcm, pcm_name, SND_PCM_STREAM_PLAYBACK, 0) < 0) {
@@ -215,11 +216,12 @@ static void flush_alsa(audio_output_t *ao)
static int close_alsa(audio_output_t *ao) static int close_alsa(audio_output_t *ao)
{ {
snd_pcm_t *pcm=(snd_pcm_t*)ao->userptr; snd_pcm_t *pcm=(snd_pcm_t*)ao->userptr;
debug1("close_alsa with %p", ao->userptr);
if(pcm != NULL) /* be really generous for being called without any device opening */ if(pcm != NULL) /* be really generous for being called without any device opening */
{ {
if (snd_pcm_state(pcm) == SND_PCM_STATE_RUNNING) if (snd_pcm_state(pcm) == SND_PCM_STATE_RUNNING)
snd_pcm_drain(pcm); snd_pcm_drain(pcm);
ao->userptr = NULL; /* Should alsa do this or the module wrapper? */
return snd_pcm_close(pcm); return snd_pcm_close(pcm);
} }
else return 0; else return 0;