summaryrefslogtreecommitdiff
path: root/src/audio_out
diff options
context:
space:
mode:
Diffstat (limited to 'src/audio_out')
-rw-r--r--src/audio_out/Makefile.am23
-rw-r--r--src/audio_out/audio_alsa_out.c370
-rw-r--r--src/audio_out/audio_arts_out.c34
-rw-r--r--src/audio_out/audio_coreaudio_out.c72
-rw-r--r--src/audio_out/audio_directx2_out.c482
-rw-r--r--src/audio_out/audio_directx_out.c80
-rw-r--r--src/audio_out/audio_esd_out.c90
-rw-r--r--src/audio_out/audio_file_out.c22
-rw-r--r--src/audio_out/audio_fusionsound_out.c82
-rw-r--r--src/audio_out/audio_irixal_out.c28
-rw-r--r--src/audio_out/audio_jack_out.c1130
-rw-r--r--src/audio_out/audio_none_out.c28
-rw-r--r--src/audio_out/audio_oss_out.c243
-rw-r--r--src/audio_out/audio_pulse_out.c771
-rw-r--r--src/audio_out/audio_sndio_out.c414
-rw-r--r--src/audio_out/audio_sun_out.c68
16 files changed, 2533 insertions, 1404 deletions
diff --git a/src/audio_out/Makefile.am b/src/audio_out/Makefile.am
index b0c3d292e..745fafadd 100644
--- a/src/audio_out/Makefile.am
+++ b/src/audio_out/Makefile.am
@@ -1,3 +1,4 @@
+include $(top_builddir)/misc/Makefile.plugins
include $(top_srcdir)/misc/Makefile.common
AM_CPPFLAGS = -DXINE_COMPILE
@@ -49,10 +50,14 @@ if HAVE_JACK
jack_module = xineplug_ao_out_jack.la
endif
+if HAVE_SNDIO
+sndio_module = xineplug_ao_out_sndio.la
+endif
+
##
# IMPORTANT:
# ---------
-# all xine audio out plugins should be named like the
+# all xine audio out plugins should be named like the
# scheme "xineplug_ao_out_"
#
xineplug_LTLIBRARIES = xineplug_ao_out_none.la xineplug_ao_out_file.la \
@@ -66,7 +71,8 @@ xineplug_LTLIBRARIES = xineplug_ao_out_none.la xineplug_ao_out_file.la \
$(pulseaudio_module) \
$(directx2_module) \
$(fusionsound_module) \
- $(jack_module)
+ $(jack_module) \
+ $(sndio_module)
xineplug_ao_out_none_la_SOURCES = audio_none_out.c
xineplug_ao_out_none_la_LIBADD = $(XINE_LIB) $(LTLIBINTL)
@@ -88,7 +94,7 @@ xineplug_ao_out_alsa_la_LIBADD = $(XINE_LIB) $(ALSA_LIBS) $(PTHREAD_LIBS) $(LTLI
xineplug_ao_out_alsa_la_CFLAGS = $(VISIBILITY_FLAG) $(ALSA_CFLAGS)
xineplug_ao_out_alsa_la_LDFLAGS = -avoid-version -module
-xineplug_ao_out_esd_la_SOURCES = audio_esd_out.c
+xineplug_ao_out_esd_la_SOURCES = audio_esd_out.c
xineplug_ao_out_esd_la_LIBADD = $(XINE_LIB) $(ESD_LIBS) $(LTLIBINTL)
xineplug_ao_out_esd_la_CFLAGS = $(VISIBILITY_FLAG) $(ESD_CFLAGS)
xineplug_ao_out_esd_la_LDFLAGS = -avoid-version -module
@@ -98,7 +104,7 @@ xineplug_ao_out_sun_la_LIBADD = $(XINE_LIB)
xineplug_ao_out_sun_la_CFLAGS = $(VISIBILITY_FLAG)
xineplug_ao_out_sun_la_LDFLAGS = -avoid-version -module
-#xineplug_ao_out_irixal_la_SOURCES = audio_irixal_out.c
+#xineplug_ao_out_irixal_la_SOURCES = audio_irixal_out.c
#xineplug_ao_out_irixal_la_LIBADD = $(IRIXAL_LIBS)
#xineplug_ao_out_irixal_la_CFLAGS = $(VISIBILITY_FLAG) $(IRIXAL_CFLAGS)
#xineplug_ao_out_irixal_la_LDFLAGS = -avoid-version -module
@@ -110,7 +116,7 @@ xineplug_ao_out_arts_la_LDFLAGS = -avoid-version -module
xineplug_ao_out_directx_la_SOURCES = audio_directx_out.c
xineplug_ao_out_directx_la_CPPFLAGS = $(DIRECTX_CPPFLAGS)
-xineplug_ao_out_directx_la_LIBADD = $(XINE_LIB) $(DIRECTX_AUDIO_LIBS)
+xineplug_ao_out_directx_la_LIBADD = $(XINE_LIB) $(DIRECTX_AUDIO_LIBS) $(LTLIBINTL)
xineplug_ao_out_directx_la_CFLAGS = $(VISIBILITY_FLAG)
xineplug_ao_out_directx_la_LDFLAGS = -avoid-version -module
@@ -131,7 +137,7 @@ xineplug_ao_out_pulseaudio_la_LDFLAGS = -avoid-version -module
xineplug_ao_out_directx2_la_SOURCES = audio_directx2_out.c
xineplug_ao_out_directx2_la_CPPFLAGS = $(DIRECTX_CPPFLAGS)
-xineplug_ao_out_directx2_la_LIBADD = $(XINE_LIB) $(DIRECTX_AUDIO_LIBS) $(PTHREAD_LIBS)
+xineplug_ao_out_directx2_la_LIBADD = $(XINE_LIB) $(DIRECTX_AUDIO_LIBS) $(PTHREAD_LIBS) $(LTLIBINTL)
xineplug_ao_out_directx2_la_CFLAGS = $(VISIBILITY_FLAG)
xineplug_ao_out_directx2_la_LDFLAGS = -avoid-version -module
@@ -144,3 +150,8 @@ xineplug_ao_out_jack_la_SOURCES = audio_jack_out.c
xineplug_ao_out_jack_la_LIBADD = $(XINE_LIB) $(JACK_LIBS) $(LTLIBINTL)
xineplug_ao_out_jack_la_CFLAGS = $(VISIBILITY_FLAG) $(JACK_CFLAGS)
xineplug_ao_out_jack_la_LDFLAGS = -avoid-version -module
+
+xineplug_ao_out_sndio_la_SOURCES = audio_sndio_out.c
+xineplug_ao_out_sndio_la_LIBADD = $(XINE_LIB) $(SNDIO_LIBS)
+xineplug_ao_out_sndio_la_CFLAGS = $(VISIBILITY_FLAG) $(SNDIO_CFLAGS)
+xineplug_ao_out_sndio_la_LDFLAGS = -avoid-version -module
diff --git a/src/audio_out/audio_alsa_out.c b/src/audio_out/audio_alsa_out.c
index 4ce2b1be3..b18637a7b 100644
--- a/src/audio_out/audio_alsa_out.c
+++ b/src/audio_out/audio_alsa_out.c
@@ -1,23 +1,23 @@
-/*
+/*
* Copyright (C) 2000-2006 the xine project
- *
+ *
* This file is part of xine, a free video player.
- *
+ *
* xine 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.
- *
+ *
* xine 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
- * Credits go
+ * Credits go
* - for the SPDIF A/52 sync part
* - frame size calculation added (16-08-2001)
* (c) 2001 Andy Lo A Foe <andy@alsaplayer.org>
@@ -99,7 +99,7 @@ typedef struct alsa_driver_s {
uint32_t bytes_per_frame;
uint32_t bytes_in_buffer; /* number of bytes writen to audio hardware */
snd_pcm_uframes_t buffer_size;
- int32_t mmap;
+ int32_t mmap;
struct {
pthread_t thread;
@@ -136,10 +136,10 @@ static int my_snd_mixer_wait(snd_mixer_t *mixer, int timeout) {
if (count < 0)
return count;
-
+
if ((unsigned int) count > sizeof(spfds) / sizeof(spfds[0])) {
pfds = malloc(count * sizeof(*pfds));
-
+
if (!pfds)
return -ENOMEM;
@@ -169,44 +169,44 @@ static void *ao_alsa_handle_event_thread(void *data) {
int old_mute;
pthread_mutex_lock(&this->mixer.mutex);
-
+
old_mute = (this->mixer.mute & MIXER_MASK_MUTE) ? 1 : 0;
if((err = snd_mixer_handle_events(this->mixer.handle)) < 0) {
- xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: snd_mixer_handle_events(): %s\n", snd_strerror(err));
pthread_mutex_unlock(&this->mixer.mutex);
continue;
}
-
+
if((err = snd_mixer_selem_get_playback_volume(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, &left_vol)) < 0) {
- xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: snd_mixer_selem_get_playback_volume(): %s\n", snd_strerror(err));
pthread_mutex_unlock(&this->mixer.mutex);
continue;
}
-
+
if((err = snd_mixer_selem_get_playback_volume(this->mixer.elem, SND_MIXER_SCHN_FRONT_RIGHT, &right_vol)) < 0) {
- xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: snd_mixer_selem_get_playback_volume(): %s\n", snd_strerror(err));
pthread_mutex_unlock(&this->mixer.mutex);
continue;
}
-
+
if(this->mixer.mute & MIXER_HAS_MUTE_SWITCH) {
-
+
if(this->mixer.mute & MIXER_MASK_STEREO) {
snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, &swl);
mute = (swl) ? 0 : 1;
}
else {
-
+
if (this->mixer.mute & MIXER_MASK_LEFT)
snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, &swl);
-
+
if ((SND_MIXER_SCHN_FRONT_RIGHT != SND_MIXER_SCHN_UNKNOWN) && (this->mixer.mute & MIXER_MASK_RIGHT))
snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_RIGHT, &swr);
-
+
mute = (swl || swr) ? 0 : 1;
}
}
@@ -216,26 +216,26 @@ static void *ao_alsa_handle_event_thread(void *data) {
xine_audio_level_data_t data;
xine_stream_t *stream;
xine_list_iterator_t ite;
-
+
this->mixer.right_vol = right_vol;
this->mixer.left_vol = left_vol;
if(mute)
this->mixer.mute |= MIXER_MASK_MUTE;
else
this->mixer.mute &= ~MIXER_MASK_MUTE;
-
- data.right = ao_alsa_get_percent_from_volume(this->mixer.right_vol,
+
+ data.right = ao_alsa_get_percent_from_volume(this->mixer.right_vol,
this->mixer.min, this->mixer.max);
- data.left = ao_alsa_get_percent_from_volume(this->mixer.left_vol,
+ data.left = ao_alsa_get_percent_from_volume(this->mixer.left_vol,
this->mixer.min, this->mixer.max);
data.mute = (this->mixer.mute & MIXER_MASK_MUTE) ? 1 : 0;
-
+
event.type = XINE_EVENT_AUDIO_LEVEL;
event.data = &data;
event.data_length = sizeof(data);
-
+
pthread_mutex_lock(&this->class->xine->streams_lock);
- for(ite = xine_list_front(this->class->xine->streams);
+ for(ite = xine_list_front(this->class->xine->streams);
ite; ite = xine_list_next(this->class->xine->streams, ite)) {
stream = xine_list_get_value(this->class->xine->streams, ite);
event.stream = stream;
@@ -243,12 +243,12 @@ static void *ao_alsa_handle_event_thread(void *data) {
}
pthread_mutex_unlock(&this->class->xine->streams_lock);
}
-
+
pthread_mutex_unlock(&this->mixer.mutex);
}
} while(this->mixer.running);
-
+
pthread_exit(NULL);
}
@@ -261,11 +261,11 @@ static long ao_alsa_get_volume_from_percent(int val, long min, long max) {
}
/*
- * Error callback, we need to control this,
+ * Error callback, we need to control this,
* error message should be printed only in DEBUG mode.
*/
static void XINE_FORMAT_PRINTF(5, 6)
- error_callback(const char *file, int line,
+ error_callback(const char *file, int line,
const char *function, int err, const char *fmt, ...) {
#ifdef DEBUG
va_list args;
@@ -286,13 +286,13 @@ static int ao_alsa_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int
alsa_driver_t *this = (alsa_driver_t *) this_gen;
config_values_t *config = this->class->xine->config;
char *pcm_device;
- snd_pcm_stream_t direction = SND_PCM_STREAM_PLAYBACK;
+ snd_pcm_stream_t direction = SND_PCM_STREAM_PLAYBACK;
snd_pcm_hw_params_t *params;
snd_pcm_sw_params_t *swparams;
snd_pcm_access_mask_t *mask;
snd_pcm_uframes_t period_size;
- snd_pcm_uframes_t period_size_min;
- snd_pcm_uframes_t period_size_max;
+ snd_pcm_uframes_t period_size_min;
+ snd_pcm_uframes_t period_size_max;
snd_pcm_uframes_t buffer_size_min;
snd_pcm_uframes_t buffer_size_max;
snd_pcm_format_t format;
@@ -310,7 +310,7 @@ static int ao_alsa_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int
snd_pcm_hw_params_alloca(&params);
snd_pcm_sw_params_alloca(&swparams);
err = snd_output_stdio_attach(&jcd_out, stdout, 0);
-
+
switch (mode) {
case AO_CAP_MODE_MONO:
this->num_channels = 1;
@@ -336,10 +336,10 @@ static int ao_alsa_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int
pcm_device = config->lookup_entry(config, "audio.device.alsa_passthrough_device")->str_value;
break;
default:
- xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: ALSA Driver does not support the requested mode: 0x%X\n",mode);
return 0;
- }
+ }
#ifdef ALSA_LOG
printf("audio_alsa_out: Audio Device name = %s\n",pcm_device);
@@ -362,25 +362,25 @@ static int ao_alsa_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int
*/
gettimeofday(&start_time, NULL);
do {
- err = snd_pcm_open(&this->audio_fd, pcm_device, direction, open_mode);
+ err = snd_pcm_open(&this->audio_fd, pcm_device, direction, open_mode);
gettimeofday(&end_time, NULL);
if( err == -EBUSY ) {
- if( (double)end_time.tv_sec + 1E-6*end_time.tv_usec
+ if( (double)end_time.tv_sec + 1E-6*end_time.tv_usec
- (double)start_time.tv_sec - 1E-6*start_time.tv_usec > 0.8)
break;
else
usleep(10000);
}
} while( err == -EBUSY );
-
- if(err <0 ) {
- xprintf (this->class->xine, XINE_VERBOSITY_LOG,
- _("audio_alsa_out: snd_pcm_open() of %s failed: %s\n"), pcm_device, snd_strerror(err));
- xprintf (this->class->xine, XINE_VERBOSITY_LOG,
+
+ if(err <0 ) {
+ xprintf (this->class->xine, XINE_VERBOSITY_LOG,
+ _("audio_alsa_out: snd_pcm_open() of %s failed: %s\n"), pcm_device, snd_strerror(err));
+ xprintf (this->class->xine, XINE_VERBOSITY_LOG,
_("audio_alsa_out: >>> check if another program already uses PCM <<<\n"));
return 0;
}
- /* printf ("audio_alsa_out: snd_pcm_open() opened %s\n", pcm_device); */
+ /* printf ("audio_alsa_out: snd_pcm_open() opened %s\n", pcm_device); */
/* We wanted non blocking open but now put it back to normal */
//snd_pcm_nonblock(this->audio_fd, 0);
snd_pcm_nonblock(this->audio_fd, 1);
@@ -389,7 +389,7 @@ static int ao_alsa_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int
*/
err = snd_pcm_hw_params_any(this->audio_fd, params);
if (err < 0) {
- xprintf (this->class->xine, XINE_VERBOSITY_LOG,
+ xprintf (this->class->xine, XINE_VERBOSITY_LOG,
_("audio_alsa_out: broken configuration for this PCM: no configurations available: %s\n"),
snd_strerror(err));
goto close;
@@ -403,7 +403,7 @@ static int ao_alsa_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int
snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_COMPLEX);
err = snd_pcm_hw_params_set_access_mask(this->audio_fd, params, mask);
if (err < 0) {
- xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: mmap not availiable, falling back to compatiblity mode\n");
this->mmap=0;
err = snd_pcm_hw_params_set_access(this->audio_fd, params,
@@ -413,9 +413,9 @@ static int ao_alsa_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int
err = snd_pcm_hw_params_set_access(this->audio_fd, params,
SND_PCM_ACCESS_RW_INTERLEAVED);
}
-
+
if (err < 0) {
- xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: access type not available: %s\n", snd_strerror(err));
goto close;
}
@@ -438,23 +438,23 @@ static int ao_alsa_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int
case 4:
format = SND_PCM_FORMAT_FLOAT;
break;
- default:
+ default:
format = SND_PCM_FORMAT_S16;
- xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: pcm format bits=%d unknown. failed: %s\n", bits, snd_strerror(err));
break;
}
err = snd_pcm_hw_params_set_format(this->audio_fd, params, format );
if (err < 0) {
- xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: sample format non available: %s\n", snd_strerror(err));
goto close;
}
/* set the number of channels */
err = snd_pcm_hw_params_set_channels(this->audio_fd, params, this->num_channels);
if (err < 0) {
- xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
- "audio_alsa_out: Cannot set number of channels to %d (err=%d:%s)\n",
+ xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
+ "audio_alsa_out: Cannot set number of channels to %d (err=%d:%s)\n",
this->num_channels, err, snd_strerror(err));
goto close;
}
@@ -466,13 +466,13 @@ static int ao_alsa_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int
dir=0;
err = snd_pcm_hw_params_set_rate_near(this->audio_fd, params, &rate, &dir);
if (err < 0) {
- xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: rate not available: %s\n", snd_strerror(err));
goto close;
}
this->output_sample_rate = (uint32_t)rate;
if (this->input_sample_rate != this->output_sample_rate) {
- xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: audio rate : %d requested, %d provided by device/sec\n",
this->input_sample_rate, this->output_sample_rate);
}
@@ -504,7 +504,7 @@ static int ao_alsa_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int
periods=8;
err = snd_pcm_hw_params_set_periods_near(this->audio_fd, params, &periods ,&dir);
if (err < 0) {
- xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: unable to set any periods: %s\n", snd_strerror(err));
goto close;
}
@@ -512,7 +512,7 @@ static int ao_alsa_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int
dir=0;
err = snd_pcm_hw_params_set_buffer_time_near(this->audio_fd, params, &buffer_time, &dir);
if (err < 0) {
- xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: buffer time not available: %s\n", snd_strerror(err));
goto close;
}
@@ -522,7 +522,7 @@ static int ao_alsa_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int
dir=0;
err = snd_pcm_hw_params_set_period_size_near(this->audio_fd, params, &period_size, &dir);
if (err < 0) {
- xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: period time not available: %s\n", snd_strerror(err));
goto close;
}
@@ -533,7 +533,7 @@ static int ao_alsa_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int
dir=0;
err = snd_pcm_hw_params_set_buffer_size_near(this->audio_fd, params, &this->buffer_size);
if (err < 0) {
- xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: buffer time not available: %s\n", snd_strerror(err));
goto close;
}
@@ -543,22 +543,22 @@ static int ao_alsa_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int
printf("was set buffer_size = %ld\n",this->buffer_size);
#endif
if (2*period_size > this->buffer_size) {
- xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: buffer to small, could not use\n");
goto close;
}
-
+
/* write the parameters to device */
err = snd_pcm_hw_params(this->audio_fd, params);
if (err < 0) {
- xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: pcm hw_params failed: %s\n", snd_strerror(err));
goto close;
}
/* Check for pause/resume support */
this->has_pause_resume = ( snd_pcm_hw_params_can_pause (params)
&& snd_pcm_hw_params_can_resume (params) );
- xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out:open pause_resume=%d\n", this->has_pause_resume);
this->sample_rate_factor = (double) this->output_sample_rate / (double) this->input_sample_rate;
this->bytes_per_frame = snd_pcm_frames_to_bytes (this->audio_fd, 1);
@@ -568,28 +568,28 @@ static int ao_alsa_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int
/* Copy current parameters into swparams */
err = snd_pcm_sw_params_current(this->audio_fd, swparams);
if (err < 0) {
- xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: Unable to determine current swparams: %s\n", snd_strerror(err));
goto close;
}
/* align all transfers to 1 sample */
err = snd_pcm_sw_params_set_xfer_align(this->audio_fd, swparams, 1);
if (err < 0) {
- xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: Unable to set transfer alignment: %s\n", snd_strerror(err));
goto close;
}
/* allow the transfer when at least period_size samples can be processed */
err = snd_pcm_sw_params_set_avail_min(this->audio_fd, swparams, period_size);
if (err < 0) {
- xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: Unable to set available min: %s\n", snd_strerror(err));
goto close;
}
/* start the transfer when the buffer contains at least period_size samples */
err = snd_pcm_sw_params_set_start_threshold(this->audio_fd, swparams, period_size);
if (err < 0) {
- xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: Unable to set start threshold: %s\n", snd_strerror(err));
goto close;
}
@@ -597,7 +597,7 @@ static int ao_alsa_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int
/* never stop the transfer, even on xruns */
err = snd_pcm_sw_params_set_stop_threshold(this->audio_fd, swparams, this->buffer_size);
if (err < 0) {
- xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: Unable to set stop threshold: %s\n", snd_strerror(err));
goto close;
}
@@ -605,15 +605,15 @@ static int ao_alsa_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int
/* Install swparams into current parameters */
err = snd_pcm_sw_params(this->audio_fd, swparams);
if (err < 0) {
- xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: Unable to set swparams: %s\n", snd_strerror(err));
goto close;
}
#ifdef ALSA_LOG
- snd_pcm_dump_setup(this->audio_fd, jcd_out);
+ snd_pcm_dump_setup(this->audio_fd, jcd_out);
snd_pcm_sw_params_dump(swparams, jcd_out);
#endif
-
+
return this->output_sample_rate;
close:
@@ -648,7 +648,7 @@ static int ao_alsa_get_gap_tolerance (ao_driver_t *this_gen) {
/*
* Return the delay. is frames measured by looking at pending samples
*/
-/* FIXME: delay returns invalid data if status is not RUNNING.
+/* FIXME: delay returns invalid data if status is not RUNNING.
* e.g When there is an XRUN or we are in PREPARED mode.
*/
static int ao_alsa_delay (ao_driver_t *this_gen) {
@@ -678,12 +678,12 @@ static int ao_alsa_delay (ao_driver_t *this_gen) {
/*
* Handle over/under-run
*/
-static void xrun(alsa_driver_t *this)
+static void xrun(alsa_driver_t *this)
{
/* snd_pcm_status_t *status; */
int res;
- /*
+ /*
snd_pcm_status_alloca(&status);
if ((res = snd_pcm_status(this->audio_fd, status))<0) {
printf ("audio_alsa_out: status error: %s\n", snd_strerror(res));
@@ -759,7 +759,7 @@ static int ao_alsa_write(ao_driver_t *this_gen, int16_t *data, uint32_t count) {
#ifdef LOG_DEBUG
printf("audio_alsa_out:write:XRUN before\n");
snd_pcm_status(this->audio_fd, pcm_stat);
- snd_pcm_status_dump(pcm_stat, jcd_out);
+ snd_pcm_status_dump(pcm_stat, jcd_out);
#endif
if ((res = snd_pcm_prepare(this->audio_fd))<0) {
return 0;
@@ -771,14 +771,14 @@ static int ao_alsa_write(ao_driver_t *this_gen, int16_t *data, uint32_t count) {
#ifdef LOG_DEBUG
printf("audio_alsa_out:write:XRUN after\n");
#endif
- }
+ }
if ( (state != SND_PCM_STATE_PREPARED) &&
(state != SND_PCM_STATE_RUNNING) &&
(state != SND_PCM_STATE_DRAINING) ) {
- xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out:write:BAD STATE, state = %d\n",state);
}
-
+
while( number_of_frames > 0) {
if ( (state == SND_PCM_STATE_RUNNING) ) {
#ifdef LOG_DEBUG
@@ -816,7 +816,7 @@ static int ao_alsa_write(ao_driver_t *this_gen, int16_t *data, uint32_t count) {
} else if ( (state != SND_PCM_STATE_PREPARED) &&
(state != SND_PCM_STATE_RUNNING) &&
(state != SND_PCM_STATE_DRAINING) ) {
- xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out:write:BAD STATE2, state = %d, going to try XRUN\n",state);
if ((res = snd_pcm_prepare(this->audio_fd))<0) {
xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
@@ -895,7 +895,7 @@ static void ao_alsa_exit(ao_driver_t *this_gen) {
this->mixer.handle=0;
}
pthread_mutex_destroy(&this->mixer.mutex);
-
+
if (this->audio_fd) snd_pcm_close(this->audio_fd);
this->audio_fd=NULL;
free (this);
@@ -913,45 +913,45 @@ static int ao_alsa_get_property (ao_driver_t *this_gen, int property) {
case AO_PROP_PCM_VOL:
if(this->mixer.elem) {
int vol;
-
+
pthread_mutex_lock(&this->mixer.mutex);
if((err = snd_mixer_selem_get_playback_volume(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT,
&this->mixer.left_vol)) < 0) {
- xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: snd_mixer_selem_get_playback_volume(): %s\n", snd_strerror(err));
goto done;
}
-
+
if((err = snd_mixer_selem_get_playback_volume(this->mixer.elem, SND_MIXER_SCHN_FRONT_RIGHT,
&this->mixer.right_vol)) < 0) {
- xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: snd_mixer_selem_get_playback_volume(): %s\n", snd_strerror(err));
goto done;
}
-
+
done:
vol = (((ao_alsa_get_percent_from_volume(this->mixer.left_vol, this->mixer.min, this->mixer.max)) +
(ao_alsa_get_percent_from_volume(this->mixer.right_vol, this->mixer.min, this->mixer.max))) /2);
pthread_mutex_unlock(&this->mixer.mutex);
-
+
return vol;
}
break;
-
+
case AO_PROP_MUTE_VOL:
{
int mute;
-
+
pthread_mutex_lock(&this->mixer.mutex);
mute = ((this->mixer.mute & MIXER_HAS_MUTE_SWITCH) && (this->mixer.mute & MIXER_MASK_MUTE)) ? 1 : 0;
pthread_mutex_unlock(&this->mixer.mutex);
-
+
return mute;
}
break;
}
-
+
return 0;
}
@@ -970,18 +970,18 @@ static int ao_alsa_set_property (ao_driver_t *this_gen, int property, int value)
pthread_mutex_lock(&this->mixer.mutex);
this->mixer.left_vol = this->mixer.right_vol = ao_alsa_get_volume_from_percent(value, this->mixer.min, this->mixer.max);
-
+
if((err = snd_mixer_selem_set_playback_volume(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT,
this->mixer.left_vol)) < 0) {
- xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: snd_mixer_selem_get_playback_volume(): %s\n", snd_strerror(err));
pthread_mutex_unlock(&this->mixer.mutex);
return ~value;
}
-
+
if((err = snd_mixer_selem_set_playback_volume(this->mixer.elem, SND_MIXER_SCHN_FRONT_RIGHT,
this->mixer.right_vol)) < 0) {
- xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: snd_mixer_selem_get_playback_volume(): %s\n", snd_strerror(err));
pthread_mutex_unlock(&this->mixer.mutex);
return ~value;
@@ -997,20 +997,20 @@ static int ao_alsa_set_property (ao_driver_t *this_gen, int property, int value)
if(this->mixer.mute & MIXER_HAS_MUTE_SWITCH) {
int swl = 0, swr = 0;
int old_mute;
-
+
pthread_mutex_lock(&this->mixer.mutex);
-
+
old_mute = this->mixer.mute;
if(value)
this->mixer.mute |= MIXER_MASK_MUTE;
else
this->mixer.mute &= ~MIXER_MASK_MUTE;
-
+
if ((this->mixer.mute & MIXER_MASK_MUTE) != (old_mute & MIXER_MASK_MUTE)) {
if(this->mixer.mute & MIXER_MASK_STEREO) {
snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, &swl);
snd_mixer_selem_set_playback_switch_all(this->mixer.elem, !swl);
- }
+ }
else {
if (this->mixer.mute & MIXER_MASK_LEFT) {
snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, &swl);
@@ -1050,7 +1050,7 @@ static int ao_alsa_ctrl(ao_driver_t *this_gen, int cmd, ...) {
if (this->audio_fd) {
if (this->has_pause_resume) {
if ((err=snd_pcm_pause(this->audio_fd, 1)) < 0) {
- xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: Pause call failed. (err=%d:%s)\n",err, snd_strerror(err));
this->has_pause_resume = 0;
ao_alsa_ctrl(this_gen, AO_CTRL_PLAY_PAUSE, NULL);
@@ -1059,15 +1059,15 @@ static int ao_alsa_ctrl(ao_driver_t *this_gen, int cmd, ...) {
}
} else {
if ((err=snd_pcm_reset(this->audio_fd)) < 0) {
- xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: Reset call failed. (err=%d:%s)\n",err, snd_strerror(err));
}
if ((err=snd_pcm_drain(this->audio_fd)) < 0) {
- xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: Drain call failed. (err=%d:%s)\n",err, snd_strerror(err));
}
if ((err=snd_pcm_prepare(this->audio_fd)) < 0) {
- xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: Prepare call failed. (err=%d:%s)\n",err, snd_strerror(err));
}
}
@@ -1079,12 +1079,12 @@ static int ao_alsa_ctrl(ao_driver_t *this_gen, int cmd, ...) {
if (this->has_pause_resume && this->is_paused) {
if ((err=snd_pcm_pause(this->audio_fd, 0)) < 0) {
if (err == -77) {
- xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: Warning: How am I supposed to RESUME, if I am not PAUSED. "
"audio_out.c, please don't call me!\n");
break;
}
- xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: Resume call failed. (err=%d:%s)\n",err, snd_strerror(err));
this->has_pause_resume = 0;
} else {
@@ -1097,11 +1097,11 @@ static int ao_alsa_ctrl(ao_driver_t *this_gen, int cmd, ...) {
case AO_CTRL_FLUSH_BUFFERS:
if (this->audio_fd) {
if ((err=snd_pcm_drop(this->audio_fd)) < 0) {
- xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: Drop call failed. (err=%d:%s)\n",err, snd_strerror(err));
}
if ((err=snd_pcm_prepare(this->audio_fd)) < 0) {
- xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: Prepare call failed. (err=%d:%s)\n",err, snd_strerror(err));
}
}
@@ -1129,43 +1129,43 @@ static void ao_alsa_mixer_init(ao_driver_t *this_gen) {
int found;
int swl = 0, swr = 0, send_events;
- this->mixer.elem = 0;
+ this->mixer.elem = 0;
snd_ctl_card_info_alloca(&hw_info);
pcm_device = config->lookup_entry(config, "audio.device.alsa_default_device")->str_value;
if ((err = snd_ctl_open (&ctl_handle, pcm_device, 0)) < 0) {
xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: snd_ctl_open(): %s\n", snd_strerror(err));
return;
}
-
+
if ((err = snd_ctl_card_info (ctl_handle, hw_info)) < 0) {
xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: snd_ctl_card_info(): %s\n", snd_strerror(err));
snd_ctl_close(ctl_handle);
return;
}
-
+
snd_ctl_close (ctl_handle);
- /*
+ /*
* Open mixer device
*/
if ((err = snd_mixer_open (&this->mixer.handle, 0)) < 0) {
- xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: snd_mixer_open(): %s\n", snd_strerror(err));
this->mixer.handle=0;
return;
}
-
+
if ((err = snd_mixer_attach (this->mixer.handle, pcm_device)) < 0) {
- xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: snd_mixer_attach(): %s\n", snd_strerror(err));
snd_mixer_close(this->mixer.handle);
this->mixer.handle=0;
return;
}
-
+
if ((err = snd_mixer_selem_register (this->mixer.handle, NULL, NULL)) < 0) {
- xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: snd_mixer_selem_register(): %s\n", snd_strerror(err));
snd_mixer_close(this->mixer.handle);
this->mixer.handle=0;
@@ -1173,77 +1173,77 @@ static void ao_alsa_mixer_init(ao_driver_t *this_gen) {
}
if ((err = snd_mixer_load (this->mixer.handle)) < 0) {
- xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: snd_mixer_load(): %s\n", snd_strerror(err));
snd_mixer_close(this->mixer.handle);
this->mixer.handle=0;
return;
}
-
+
mixer_sid = alloca(snd_mixer_selem_id_sizeof() * snd_mixer_get_count(this->mixer.handle));
if (mixer_sid == NULL) {
- xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: alloca() failed: %s\n", strerror(errno));
snd_mixer_close(this->mixer.handle);
this->mixer.handle=0;
return;
}
-
+
again:
found = 0;
mixer_n_selems = 0;
for (elem = snd_mixer_first_elem(this->mixer.handle); elem; elem = snd_mixer_elem_next(elem)) {
sid = (snd_mixer_selem_id_t *)(((char *)mixer_sid) + snd_mixer_selem_id_sizeof() * mixer_n_selems);
-
+
if ((snd_mixer_elem_get_type(elem) != SND_MIXER_ELEM_SIMPLE) ||
!snd_mixer_selem_is_active(elem))
continue;
-
+
snd_mixer_selem_get_id(elem, sid);
mixer_n_selems++;
if(!strcmp((snd_mixer_selem_get_name(elem)), this->mixer.name)) {
/* printf("found %s\n", snd_mixer_selem_get_name(elem)); */
-
+
this->mixer.elem = elem;
-
- snd_mixer_selem_get_playback_volume_range(this->mixer.elem,
+
+ snd_mixer_selem_get_playback_volume_range(this->mixer.elem,
&this->mixer.min, &this->mixer.max);
if((err = snd_mixer_selem_get_playback_volume(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT,
&this->mixer.left_vol)) < 0) {
- xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: snd_mixer_selem_get_playback_volume(): %s\n", snd_strerror(err));
this->mixer.elem = NULL;
continue;
}
-
+
if((err = snd_mixer_selem_get_playback_volume(this->mixer.elem, SND_MIXER_SCHN_FRONT_RIGHT,
&this->mixer.right_vol)) < 0) {
- xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: snd_mixer_selem_get_playback_volume(): %s\n", snd_strerror(err));
this->mixer.elem = NULL;
continue;
}
-
+
/* Channels mute */
this->mixer.mute = 0;
if(snd_mixer_selem_has_playback_switch(this->mixer.elem)) {
this->mixer.mute |= MIXER_HAS_MUTE_SWITCH;
-
+
if (snd_mixer_selem_has_playback_switch_joined(this->mixer.elem)) {
this->mixer.mute |= MIXER_MASK_STEREO;
snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, &swl);
- }
+ }
else {
this->mixer.mute |= MIXER_MASK_LEFT;
snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, &swl);
-
+
if (SND_MIXER_SCHN_FRONT_RIGHT != SND_MIXER_SCHN_UNKNOWN) {
this->mixer.mute |= MIXER_MASK_RIGHT;
snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_RIGHT, &swr);
}
-
+
if(!swl || !swr)
this->mixer.mute |= MIXER_MASK_MUTE;
}
@@ -1256,10 +1256,10 @@ static void ao_alsa_mixer_init(ao_driver_t *this_gen) {
goto mixer_found;
}
}
-
+
if(loop)
goto mixer_found; /* Yes, untrue but... ;-) */
-
+
if(!strcmp(this->mixer.name, "PCM")) {
config->update_string(config, "audio.device.alsa_mixer_name", "Master");
loop++;
@@ -1267,14 +1267,14 @@ static void ao_alsa_mixer_init(ao_driver_t *this_gen) {
else {
config->update_string(config, "audio.device.alsa_mixer_name", "PCM");
}
-
+
this->mixer.name = config->lookup_entry(config, "audio.device.alsa_mixer_name")->str_value;
-
+
goto again;
mixer_found:
-
- /*
+
+ /*
* Ugly: yes[*] no[ ]
*/
if(found) {
@@ -1301,11 +1301,11 @@ static void ao_alsa_mixer_init(ao_driver_t *this_gen) {
if (send_events && found) {
pthread_attr_t pth_attrs;
struct sched_param pth_params;
-
+
this->mixer.running = 1;
pthread_attr_init(&pth_attrs);
-
+
pthread_attr_getschedparam(&pth_attrs, &pth_params);
pth_params.sched_priority = sched_get_priority_min(SCHED_OTHER);
pthread_attr_setschedparam(&pth_attrs, &pth_params);
@@ -1317,7 +1317,7 @@ static void ao_alsa_mixer_init(ao_driver_t *this_gen) {
}
static void alsa_speaker_arrangement_cb (void *user_data,
- xine_cfg_entry_t *entry);
+ xine_cfg_entry_t *entry);
/*
* Initialize plugin
@@ -1350,7 +1350,7 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da
#define A52_PASSTHRU 12
int speakers;
- this = (alsa_driver_t *) xine_xmalloc (sizeof (alsa_driver_t));
+ this = calloc(1, sizeof (alsa_driver_t));
if (!this)
return NULL;
@@ -1358,8 +1358,8 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da
err = snd_lib_error_set_handler(error_callback);
if(err < 0)
- xine_log(this->class->xine, XINE_LOG_MSG, _("snd_lib_error_set_handler() failed: %d"), err);
-
+ xine_log(this->class->xine, XINE_LOG_MSG, _("snd_lib_error_set_handler() failed: %d"), err);
+
snd_pcm_hw_params_alloca(&params);
this->mmap = config->register_bool (config,
@@ -1424,7 +1424,7 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da
/* Use the default device to open first */
pcm_device = config->lookup_entry(config, "audio.device.alsa_default_device")->str_value;
-
+
/*
* find best device driver/channel
*/
@@ -1434,11 +1434,11 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da
err=snd_pcm_open(&this->audio_fd, pcm_device, SND_PCM_STREAM_PLAYBACK, 1); /* NON-BLOCK mode */
if(err <0 ) {
xine_log (this->class->xine, XINE_LOG_MSG,
- _("snd_pcm_open() failed:%d:%s\n"), err, snd_strerror(err));
+ _("snd_pcm_open() failed:%d:%s\n"), err, snd_strerror(err));
xine_log (this->class->xine, XINE_LOG_MSG,
- _(">>> Check if another program already uses PCM <<<\n"));
+ _(">>> Check if another program already uses PCM <<<\n"));
free(this);
- return NULL;
+ return NULL;
}
/*
@@ -1446,7 +1446,7 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da
*/
err = snd_pcm_hw_params_any(this->audio_fd, params);
if (err < 0) {
- xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: broken configuration for this PCM: no configurations available\n");
snd_pcm_close(this->audio_fd);
free(this);
@@ -1455,7 +1455,7 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da
err = snd_pcm_hw_params_set_access(this->audio_fd, params,
SND_PCM_ACCESS_RW_INTERLEAVED);
if (err < 0) {
- xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
"audio_alsa_out: access type not available");
snd_pcm_close(this->audio_fd);
free(this);
@@ -1497,70 +1497,73 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da
"formats you want to play to your sound card's digital output."),
0, alsa_speaker_arrangement_cb, this);
- xprintf(class->xine, XINE_VERBOSITY_LOG, _("audio_alsa_out : supported modes are "));
+ char *logmsg = strdup (_("audio_alsa_out : supported modes are"));
+
if (!(snd_pcm_hw_params_test_format(this->audio_fd, params, SND_PCM_FORMAT_U8))) {
this->capabilities |= AO_CAP_8BITS;
- xprintf(class->xine, XINE_VERBOSITY_LOG, _("8bit "));
+ xine_strcat_realloc (&logmsg, _(" 8bit"));
}
/* ALSA automatically appends _LE or _BE depending on the CPU */
if (!(snd_pcm_hw_params_test_format(this->audio_fd, params, SND_PCM_FORMAT_S16))) {
this->capabilities |= AO_CAP_16BITS;
- xprintf(class->xine, XINE_VERBOSITY_LOG, _("16bit "));
+ xine_strcat_realloc (&logmsg, _(" 16bit"));
}
if (!(snd_pcm_hw_params_test_format(this->audio_fd, params, SND_PCM_FORMAT_S24))) {
this->capabilities |= AO_CAP_24BITS;
- xprintf(class->xine, XINE_VERBOSITY_LOG, _("24bit "));
+ xine_strcat_realloc (&logmsg, _(" 24bit"));
}
if (!(snd_pcm_hw_params_test_format(this->audio_fd, params, SND_PCM_FORMAT_FLOAT))) {
this->capabilities |= AO_CAP_FLOAT32;
- xprintf(class->xine, XINE_VERBOSITY_LOG, _("32bit "));
+ xine_strcat_realloc (&logmsg, _(" 32bit"));
}
if (0 == (this->capabilities & (AO_CAP_FLOAT32 | AO_CAP_24BITS | AO_CAP_16BITS | AO_CAP_8BITS))) {
- xprintf (this->class->xine, XINE_VERBOSITY_DEBUG,
- "\naudio_alsa_out: no supported PCM format found\n");
+ xprintf(class->xine, XINE_VERBOSITY_LOG, "%s\n", logmsg);
+ free (logmsg);
+ xprintf (class->xine, XINE_VERBOSITY_DEBUG,
+ "audio_alsa_out: no supported PCM format found\n");
snd_pcm_close(this->audio_fd);
free(this);
return NULL;
}
if (!(snd_pcm_hw_params_test_channels(this->audio_fd, params, 1))) {
this->capabilities |= AO_CAP_MODE_MONO;
- xprintf(class->xine, XINE_VERBOSITY_LOG, _("mono "));
+ xine_strcat_realloc (&logmsg, _(" mono"));
}
if (!(snd_pcm_hw_params_test_channels(this->audio_fd, params, 2))) {
this->capabilities |= AO_CAP_MODE_STEREO;
- xprintf(class->xine, XINE_VERBOSITY_LOG, _("stereo "));
+ xine_strcat_realloc (&logmsg, _(" stereo"));
}
if (!(snd_pcm_hw_params_test_channels(this->audio_fd, params, 4)) &&
( speakers == SURROUND4 )) {
this->capabilities |= AO_CAP_MODE_4CHANNEL;
- xprintf(class->xine, XINE_VERBOSITY_LOG, _("4-channel "));
- }
+ xine_strcat_realloc (&logmsg, _(" 4-channel"));
+ }
else
- xprintf(class->xine, XINE_VERBOSITY_LOG, _("(4-channel not enabled in xine config) "));
-
- if (!(snd_pcm_hw_params_test_channels(this->audio_fd, params, 6)) &&
+ xine_strcat_realloc (&logmsg, _(" (4-channel not enabled in xine config)"));
+
+ if (!(snd_pcm_hw_params_test_channels(this->audio_fd, params, 6)) &&
( speakers == SURROUND41 )) {
this->capabilities |= AO_CAP_MODE_4_1CHANNEL;
- xprintf(class->xine, XINE_VERBOSITY_LOG, _("4.1-channel "));
- }
+ xine_strcat_realloc (&logmsg, _(" 4.1-channel"));
+ }
else
- xprintf(class->xine, XINE_VERBOSITY_LOG, _("(4.1-channel not enabled in xine config) "));
+ xine_strcat_realloc (&logmsg, _(" (4.1-channel not enabled in xine config)"));
- if (!(snd_pcm_hw_params_test_channels(this->audio_fd, params, 6)) &&
+ if (!(snd_pcm_hw_params_test_channels(this->audio_fd, params, 6)) &&
( speakers == SURROUND5 )) {
this->capabilities |= AO_CAP_MODE_5CHANNEL;
- xprintf(class->xine, XINE_VERBOSITY_LOG, _("5-channel "));
- }
+ xine_strcat_realloc (&logmsg, _(" 5-channel"));
+ }
else
- xprintf(class->xine, XINE_VERBOSITY_LOG, _("(5-channel not enabled in xine config) "));
+ xine_strcat_realloc (&logmsg, _(" (5-channel not enabled in xine config)"));
- if (!(snd_pcm_hw_params_test_channels(this->audio_fd, params, 6)) &&
+ if (!(snd_pcm_hw_params_test_channels(this->audio_fd, params, 6)) &&
( speakers >= SURROUND51 )) {
this->capabilities |= AO_CAP_MODE_5_1CHANNEL;
- xprintf(class->xine, XINE_VERBOSITY_LOG, _("5.1-channel "));
- }
+ xine_strcat_realloc (&logmsg, _(" 5.1-channel"));
+ }
else
- xprintf(class->xine, XINE_VERBOSITY_LOG, _("(5.1-channel not enabled in xine config) "));
+ xine_strcat_realloc (&logmsg, _(" (5.1-channel not enabled in xine config)"));
this->has_pause_resume = 0; /* This is checked at open time instead */
this->is_paused = 0;
@@ -1583,10 +1586,13 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da
if ( speakers == A52_PASSTHRU ) {
this->capabilities |= AO_CAP_MODE_A52;
this->capabilities |= AO_CAP_MODE_AC5;
- xprintf(class->xine, XINE_VERBOSITY_LOG, _("a/52 and DTS pass-through\n"));
- }
+ xine_strcat_realloc (&logmsg, _(" a/52 and DTS pass-through"));
+ }
else
- xprintf(class->xine, XINE_VERBOSITY_LOG, _("(a/52 and DTS pass-through not enabled in xine config)\n"));
+ xine_strcat_realloc (&logmsg, _(" (a/52 and DTS pass-through not enabled in xine config)"));
+
+ xprintf(class->xine, XINE_VERBOSITY_LOG, "%s\n", logmsg);
+ free (logmsg);
/* printf("audio_alsa_out: capabilities 0x%X\n",this->capabilities); */
@@ -1616,7 +1622,7 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da
this->ao_driver.num_channels = ao_alsa_num_channels;
this->ao_driver.bytes_per_frame = ao_alsa_bytes_per_frame;
this->ao_driver.delay = ao_alsa_delay;
- this->ao_driver.write = ao_alsa_write;
+ this->ao_driver.write = ao_alsa_write;
this->ao_driver.close = ao_alsa_close;
this->ao_driver.exit = ao_alsa_exit;
this->ao_driver.get_gap_tolerance = ao_alsa_get_gap_tolerance;
@@ -1682,7 +1688,7 @@ static void *init_class (xine_t *xine, void *data) {
alsa_class_t *this;
- this = (alsa_class_t *) xine_xmalloc (sizeof (alsa_class_t));
+ this = calloc(1, sizeof (alsa_class_t));
if (!this)
return NULL;
@@ -1705,7 +1711,7 @@ static ao_info_t ao_info_alsa = {
*/
const plugin_info_t xine_plugin_info[] EXPORTED = {
- /* type, API, "name", version, special_info, init_function */
+ /* type, API, "name", version, special_info, init_function */
{ PLUGIN_AUDIO_OUT, AO_OUT_ALSA_IFACE_VERSION, "alsa", XINE_VERSION_CODE, &ao_info_alsa, init_class },
{ PLUGIN_NONE, 0, "", 0, NULL, NULL }
};
diff --git a/src/audio_out/audio_arts_out.c b/src/audio_out/audio_arts_out.c
index 0f0467b4a..7f796f2b3 100644
--- a/src/audio_out/audio_arts_out.c
+++ b/src/audio_out/audio_arts_out.c
@@ -1,18 +1,18 @@
-/*
+/*
* Copyright (C) 2000-2003 the xine project
- *
+ *
* This file is part of xine, a free video player.
- *
+ *
* xine 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.
- *
+ *
* xine 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
@@ -42,7 +42,7 @@
#define AUDIO_NUM_FRAGMENTS 15
#define AUDIO_FRAGMENT_SIZE 8192
-#define GAP_TOLERANCE AO_MAX_GAP
+#define GAP_TOLERANCE AO_MAX_GAP
typedef struct arts_driver_s {
@@ -84,7 +84,7 @@ typedef struct {
static void ao_arts_volume(void *buffer, int length, int volume) {
int v;
short *data = (short *)buffer;
-
+
while (length--) {
v=(int) ((*(data) * volume) / 100);
*(data)=(v>32767) ? 32767 : ((v<-32768) ? -32768 : v);
@@ -118,7 +118,7 @@ static int ao_arts_open(ao_driver_t *this_gen,
sleep(2); /* arts might segfault if we are still playing */
arts_close_stream(this->audio_stream);
}
-
+
this->mode = mode;
this->sample_rate = rate;
this->bits_per_sample = bits;
@@ -139,7 +139,7 @@ static int ao_arts_open(ao_driver_t *this_gen,
this->audio_stream=arts_play_stream(this->sample_rate, bits, this->num_channels, "xine");
this->latency = arts_stream_get (this->audio_stream, ARTS_P_TOTAL_LATENCY);
-
+
/* try to keep latency low, if we don't do this we might end
with very high latencies for low quality sound and audio_out will
try to fill gaps every time...(values in ms) */
@@ -181,7 +181,7 @@ static int ao_arts_write(ao_driver_t *this_gen, int16_t *data,
arts_driver_t *this = (arts_driver_t *) this_gen;
int size = num_frames * this->bytes_per_frame;
- ao_arts_volume(data, num_frames * this->num_channels, this->mixer.vol_scale );
+ ao_arts_volume(data, num_frames * this->num_channels, this->mixer.vol_scale );
arts_write(this->audio_stream, data, size );
return 1;
@@ -220,7 +220,7 @@ static uint32_t ao_arts_get_capabilities (ao_driver_t *this_gen) {
static void ao_arts_exit(ao_driver_t *this_gen)
{
arts_driver_t *this = (arts_driver_t *) this_gen;
-
+
ao_arts_close(this_gen);
/* FIXME: arts_free() freezes on BSD, so don't use it there */
#if !defined(__OpenBSD__) && !defined (__FreeBSD__) && !defined(__NetBSD__)
@@ -233,7 +233,7 @@ static void ao_arts_exit(ao_driver_t *this_gen)
static int ao_arts_get_property (ao_driver_t *this_gen, int property) {
arts_driver_t *this = (arts_driver_t *) this_gen;
-
+
switch(property) {
case AO_PROP_PCM_VOL:
case AO_PROP_MIXER_VOL:
@@ -269,7 +269,7 @@ static int ao_arts_set_property (ao_driver_t *this_gen, int property, int value)
} else {
this->mixer.volume = this->mixer.v_mixer;
this->mixer.vol_scale = this->mixer.volume;
- }
+ }
this->mixer.mute = mute;
return value;
break;
@@ -303,7 +303,7 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da
lprintf ("audio_arts_out: open_plugin called\n");
- this = (arts_driver_t *) xine_xmalloc (sizeof (arts_driver_t));
+ this = calloc(1, sizeof (arts_driver_t));
if (!this)
return NULL;
@@ -323,7 +323,7 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da
free(this);
return NULL;
}
-
+
/*
* set volume control
*/
@@ -384,7 +384,7 @@ static void *init_class (xine_t *xine, void *data) {
lprintf ("audio_arts_out: init class\n");
- this = (arts_class_t *) xine_xmalloc (sizeof (arts_class_t));
+ this = calloc(1, sizeof (arts_class_t));
if (!this)
return NULL;
@@ -409,7 +409,7 @@ static ao_info_t ao_info_arts = {
*/
const plugin_info_t xine_plugin_info[] EXPORTED = {
- /* type, API, "name", version, special_info, init_function */
+ /* type, API, "name", version, special_info, init_function */
{ PLUGIN_AUDIO_OUT, AO_OUT_ARTS_IFACE_VERSION, "arts", XINE_VERSION_CODE, &ao_info_arts, init_class },
{ PLUGIN_NONE, 0, "", 0, NULL, NULL }
};
diff --git a/src/audio_out/audio_coreaudio_out.c b/src/audio_out/audio_coreaudio_out.c
index eecab8f95..5e31a15e5 100644
--- a/src/audio_out/audio_coreaudio_out.c
+++ b/src/audio_out/audio_coreaudio_out.c
@@ -1,18 +1,18 @@
-/*
+/*
* Copyright (C) 2000-2004 the xine project
- *
+ *
* This file is part of xine, a free video player.
- *
+ *
* xine 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.
- *
+ *
* xine 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
@@ -54,7 +54,7 @@
#define AO_OUT_COREAUDIO_IFACE_VERSION 8
-#define GAP_TOLERANCE AO_MAX_GAP
+#define GAP_TOLERANCE AO_MAX_GAP
#define BUFSIZE 30720
/* Number of seconds to wait for buffered data to arrive/be used
* before giving up. */
@@ -75,7 +75,7 @@ typedef struct coreaudio_driver_s {
Component au_component;
Component converter_component;
-
+
AudioUnit au_unit;
AudioUnit converter_unit;
@@ -86,7 +86,7 @@ typedef struct coreaudio_driver_s {
int mute;
Float32 pre_mute_volume;
-
+
pthread_mutex_t mutex;
pthread_cond_t buffer_ready_for_reading;
pthread_cond_t buffer_ready_for_writing;
@@ -131,7 +131,7 @@ static OSStatus ao_coreaudio_render_proc (coreaudio_driver_t *this,
pthread_mutex_lock (&this->mutex);
if(this->buf_head < ((BUFSIZE) >> 2)) {
set_to_future(&future);
- if(pthread_cond_timedwait
+ if(pthread_cond_timedwait
(&this->buffer_ready_for_reading, &this->mutex, &future) == ETIMEDOUT)
{
/* Timed out, give up and fill remainder with silence. */
@@ -143,13 +143,13 @@ static OSStatus ao_coreaudio_render_proc (coreaudio_driver_t *this,
return noErr;
}
}
-
+
if(this->buf_head < buffer_size - buffer_progress) {
chunk_size = this->buf_head;
} else {
chunk_size = buffer_size - buffer_progress;
}
-
+
xine_fast_memcpy (ioData->mBuffers[i].mData, this->buf, chunk_size);
if(chunk_size < this->buf_head) {
memmove(this->buf, &(this->buf[chunk_size]), this->buf_head - chunk_size);
@@ -188,7 +188,7 @@ static int ao_coreaudio_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate
AudioStreamBasicDescription format;
AudioUnitConnection connection;
ComponentDescription desc;
-
+
switch (mode) {
case AO_CAP_MODE_MONO:
this->num_channels = 1;
@@ -209,7 +209,7 @@ static int ao_coreaudio_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate
pthread_cond_init (&this->buffer_ready_for_reading, NULL);
pthread_cond_init (&this->buffer_ready_for_writing, NULL);
- xprintf (this->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG,
"audio_coreaudio_out: ao_open bits=%d rate=%d, mode=%d\n", bits, rate, mode);
/* find an audio output unit */
@@ -218,17 +218,17 @@ static int ao_coreaudio_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
-
+
this->au_component = FindNextComponent (NULL, &desc);
if (this->au_component == NULL) {
- xprintf (this->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG,
"audio_coreaudio_out: Unable to find a usable audio output unit component\n");
return 0;
}
-
+
OpenAComponent (this->au_component, &this->au_unit);
-
+
/* find a converter unit */
desc.componentType = kAudioUnitType_FormatConverter;
desc.componentSubType = kAudioUnitSubType_AUConverter;
@@ -236,11 +236,11 @@ static int ao_coreaudio_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate
this->converter_component = FindNextComponent (NULL, &desc);
if (this->converter_component == NULL) {
- xprintf (this->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG,
"audio_coreaudio_out: Unable to find a usable audio converter unit component\n");
return 0;
}
-
+
OpenAComponent (this->converter_component, &this->converter_unit);
/* set up the render procedure */
@@ -258,7 +258,7 @@ static int ao_coreaudio_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate
connection.destInputNumber = 0;
AudioUnitSetProperty (this->au_unit,
kAudioUnitProperty_MakeConnection,
- kAudioUnitScope_Input, 0,
+ kAudioUnitScope_Input, 0,
&connection, sizeof(connection));
/* set up the audio format we want to use */
@@ -274,7 +274,7 @@ static int ao_coreaudio_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate
format.mBytesPerFrame = this->bytes_per_frame;
format.mFramesPerPacket = 1;
format.mBytesPerPacket = format.mBytesPerFrame;
-
+
AudioUnitSetProperty (this->converter_unit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
@@ -339,7 +339,7 @@ static int ao_coreaudio_write(ao_driver_t *this_gen, int16_t *data,
pthread_mutex_lock (&this->mutex);
if(this->buf_head > ((3 * BUFSIZE)>>2)) {
set_to_future(&future);
- if(pthread_cond_timedwait
+ if(pthread_cond_timedwait
(&this->buffer_ready_for_writing, &this->mutex, &future) == ETIMEDOUT)
{
/* Timed out, give up. */
@@ -354,10 +354,10 @@ static int ao_coreaudio_write(ao_driver_t *this_gen, int16_t *data,
} else {
chunk_size = remaining_bytes;
}
-
+
xine_fast_memcpy(&(this->buf[this->buf_head]), data, chunk_size);
this->buf_head += chunk_size;
- remaining_bytes -= chunk_size;
+ remaining_bytes -= chunk_size;
if(this->buf_head > 0) {
pthread_cond_broadcast (&this->buffer_ready_for_reading);
@@ -389,13 +389,13 @@ static void ao_coreaudio_close(ao_driver_t *this_gen)
CloseComponent (this->au_unit);
this->au_unit = 0;
}
-
+
if (this->converter_unit) {
AudioUnitUninitialize (this->converter_unit);
CloseComponent (this->converter_unit);
this->converter_unit = 0;
}
-
+
if (this->au_component) {
this->au_component = NULL;
}
@@ -417,7 +417,7 @@ static uint32_t ao_coreaudio_get_capabilities (ao_driver_t *this_gen) {
static void ao_coreaudio_exit(ao_driver_t *this_gen)
{
coreaudio_driver_t *this = (coreaudio_driver_t *) this_gen;
-
+
ao_coreaudio_close(this_gen);
free (this);
@@ -436,7 +436,7 @@ static int ao_coreaudio_get_property (ao_driver_t *this_gen, int property) {
kAudioUnitScope_Output,
0, &val);
} else {
- val = this->pre_mute_volume;
+ val = this->pre_mute_volume;
}
return (int) (val * 12);
break;
@@ -472,12 +472,12 @@ static int ao_coreaudio_set_property (ao_driver_t *this_gen, int property, int v
kHALOutputParam_Volume,
kAudioUnitScope_Output,
0, &(this->pre_mute_volume));
-
+
AudioUnitSetParameter (this->au_unit,
kHALOutputParam_Volume,
kAudioUnitScope_Output,
0, 0, 0);
-
+
this->mute = 1;
}
} else {
@@ -487,14 +487,14 @@ static int ao_coreaudio_set_property (ao_driver_t *this_gen, int property, int v
kHALOutputParam_Volume,
kAudioUnitScope_Output,
0, this->pre_mute_volume, 0);
-
+
this->mute = 0;
}
}
return value;
break;
}
-
+
return ~value;
}
@@ -521,7 +521,7 @@ static int ao_coreaudio_ctrl(ao_driver_t *this_gen, int cmd, ...) {
return 0;
}
-static ao_driver_t *open_plugin (audio_driver_class_t *class_gen,
+static ao_driver_t *open_plugin (audio_driver_class_t *class_gen,
const void *data) {
coreaudio_class_t *class = (coreaudio_class_t *) class_gen;
@@ -530,7 +530,7 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen,
lprintf ("open_plugin called\n");
- this = (coreaudio_driver_t *) xine_xmalloc (sizeof (coreaudio_driver_t));
+ this = calloc(1, sizeof (coreaudio_driver_t));
if (!this)
return NULL;
@@ -582,7 +582,7 @@ static void *init_class (xine_t *xine, void *data) {
lprintf ("init class\n");
- this = (coreaudio_class_t *) xine_xmalloc (sizeof (coreaudio_class_t));
+ this = calloc(1, sizeof (coreaudio_class_t));
if (!this)
return NULL;
@@ -606,7 +606,7 @@ static const ao_info_t ao_info_coreaudio = {
*/
const plugin_info_t xine_plugin_info[] EXPORTED = {
- /* type, API, "name", version, special_info, init_function */
+ /* type, API, "name", version, special_info, init_function */
{ PLUGIN_AUDIO_OUT, AO_OUT_COREAUDIO_IFACE_VERSION, "coreaudio", XINE_VERSION_CODE, &ao_info_coreaudio, init_class },
{ PLUGIN_NONE, 0, "", 0, NULL, NULL }
};
diff --git a/src/audio_out/audio_directx2_out.c b/src/audio_out/audio_directx2_out.c
index d9688b647..4d7fe4e65 100644
--- a/src/audio_out/audio_directx2_out.c
+++ b/src/audio_out/audio_directx2_out.c
@@ -31,6 +31,9 @@
*
* Authors:
* - Frantisek Dvorak <valtri@atlas.cz>
+ * - Original version with slotted ring buffer
+ * - Matthias Ringald <mringwal@inf.ethz.ch>
+ * - non-slotted simpler version for ring buffer handling
*
* Inspiration:
* - mplayer for workarounding -lguid idea
@@ -55,8 +58,8 @@
#define LOG_MODULE "audio_directx2_out"
#define LOG_VERBOSE
/*
-#define LOG
-*/
+ #define LOG
+ */
#include "xine_internal.h"
#include "audio_out.h"
@@ -64,29 +67,33 @@
#define AO_OUT_DIRECTX2_IFACE_VERSION 8
-/*
- * buffer size in miliseconds
- * (one second takes 11-192 KB)
+
+/*
+ * If GAP_TOLERANCE is lower than AO_MAX_GAP, xine will
+ * try to smooth playback without skipping frames or
+ * inserting silence.
+ */
+#define GAP_TOLERANCE (AO_MAX_GAP/3)
+
+/*
+ * buffer size in miliseconds
+ * (one second takes 11-192 KB)
*/
#define BUFFER_MS 1000
-/*
- * number of parts in the buffer,
- * one is always locked for playing
+/*
+ * buffer below this threshold is considered a buffer underrun
*/
-#define PARTS 3
+#define BUFFER_MIN_MS 200
-/*
+/*
* base power factor for volume remapping
*/
#define FACTOR 60.0
-
-/* experiments */
-/*#define EXACT_WAIT*/
-/*#define EXACT_SLEEP*/
-/*#define PANIC_OVERRUN*/
-
+/*
+ * buffer handler status
+ */
#define STATUS_START 0
#define STATUS_WAIT 1
#define STATUS_RUNNING 2
@@ -108,12 +115,14 @@ typedef struct {
LPDIRECTSOUND ds; /* DirectSound device */
LPDIRECTSOUNDBUFFER dsbuffer; /* DirectSound buffer */
- DSBPOSITIONNOTIFY events[PARTS]; /* position events */
- LPDIRECTSOUNDNOTIFY notify; /* notify interface */
size_t buffer_size; /* size of the buffer */
- size_t part_size; /* second half of buffer */
- size_t read_size; /* size of prepared data */
+ size_t write_pos; /* positition in ring buffer for writing*/
+
+ int status; /* current status of the driver */
+ int paused; /* paused mode */
+ int finished; /* driver finished */
+ int failed; /* don't open modal dialog again */
uint32_t bits;
uint32_t rate;
@@ -123,12 +132,6 @@ typedef struct {
int volume;
int muted;
- int status; /* current status of the driver */
- int paused; /* paused mode */
- int finished; /* driver finished */
- int failed; /* don't open modal dialog again */
- int count; /* current free part number */
-
pthread_t buffer_service; /* service thread for operating with DSB */
pthread_cond_t data_cond; /* signals on data */
pthread_mutex_t data_mutex; /* data lock */
@@ -140,17 +143,19 @@ typedef struct {
* Defining them here allows us to get rid of the dxguid library during
* the linking stage.
*****************************************************************************/
-static const GUID IID_IDirectSoundNotify = {
- 0xB0210783, 0x89CD, 0x11D0, {0xAF, 0x08, 0x00, 0xA0, 0xC9, 0x25, 0xCD, 0x16}
+static const GUID xine_IID_IDirectSoundNotify = {
+0xB0210783, 0x89CD, 0x11D0, {0xAF, 0x08, 0x00, 0xA0, 0xC9, 0x25, 0xCD, 0x16}
};
+#ifdef IID_IDirectSoundNotify
+# undef IID_IDirectSoundNotify
+#endif
+#define IID_IDirectSoundNotify xine_IID_IDirectSoundNotify
-static int buffer_ready(dx2_driver_t *this);
-
/* popup a dialog with error */
static void XINE_FORMAT_PRINTF(1, 2)
- error_message(const char *fmt, ...) {
+error_message(const char *fmt, ...) {
char message[256];
va_list ap;
@@ -214,7 +219,7 @@ static LPDIRECTSOUND dsound_create() {
/* destroy direct sound object */
static void dsound_destroy(LPDIRECTSOUND ds) {
- IDirectSound_Release(ds);
+ IDirectSound_Release(ds);
}
@@ -266,12 +271,10 @@ static int audio_create_buffers(dx2_driver_t *this) {
HRESULT err;
size_t buffer_size;
- buffer_size = this->rate * this->frame_size * BUFFER_MS / 1000;
+ buffer_size = this->rate * BUFFER_MS / 1000 * this->frame_size;
if (buffer_size > DSBSIZE_MAX) buffer_size = DSBSIZE_MAX;
if (buffer_size < DSBSIZE_MIN) buffer_size = DSBSIZE_MIN;
- this->part_size = (buffer_size / PARTS / this->frame_size) * this->frame_size;
- if (!this->part_size) this->part_size = this->frame_size;
- this->buffer_size = this->part_size * PARTS;
+ this->buffer_size = buffer_size;
flags = DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY;
dsound_fill_wfx(&wfx, this->bits, this->rate, this->channels, this->frame_size);
@@ -282,7 +285,7 @@ static int audio_create_buffers(dx2_driver_t *this) {
return 0;
}
- lprintf("created direct sound buffer, size = %u, part = %u\n", this->buffer_size, this->part_size);
+ lprintf("created direct sound buffer, size = %u\n", this->buffer_size);
return 1;
}
@@ -293,43 +296,6 @@ static void audio_destroy_buffers(dx2_driver_t *this) {
}
-/* create position events */
-static int audio_create_events(dx2_driver_t *this) {
- HANDLE handle[PARTS];
- HRESULT err;
- int i;
-
- for (i = 0; i < PARTS; i++) {
- handle[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
- if (!handle[i]) {
- error_message(_("Unable to create buffer position events."));
- return 0;
- }
- this->events[i].dwOffset = i * this->part_size;
- this->events[i].hEventNotify = handle[i];
- }
-
- if ((err = IDirectSoundBuffer_QueryInterface(this->dsbuffer, &IID_IDirectSoundNotify, (void **)&this->notify)) != DS_OK) {
- audio_error(this, err, _("Unable to get notification interface"));
- return 0;
- }
-
- if ((err = IDirectSoundNotify_SetNotificationPositions(this->notify, PARTS, this->events)) != DS_OK) {
- audio_error(this, err, _("Unable to set notification positions"));
- IDirectSoundNotify_Release(this->notify);
- return 0;
- }
-
- return 1;
-}
-
-
-/* destroy notification interface */
-static void audio_destroy_events(dx2_driver_t *this) {
- IDirectSoundNotify_Release(this->notify);
-}
-
-
/* start playback */
static int audio_play(dx2_driver_t *this) {
HRESULT err;
@@ -385,13 +351,12 @@ static int audio_seek(dx2_driver_t *this, size_t pos) {
/* flush audio buffers */
static int audio_flush(dx2_driver_t *this) {
this->status = STATUS_WAIT;
- this->count = 0;
- this->read_size = 0;
+ this->write_pos = 0;
return audio_seek(this, 0);
}
-/*
+/*
* set the volume
*
* DirecSound can only lower the volume by software way.
@@ -421,12 +386,12 @@ static int audio_fill(dx2_driver_t *this, char *data, size_t size) {
HRESULT err;
/* lock a part of the buffer, begin position on free space */
- err = IDirectSoundBuffer_Lock(this->dsbuffer, (this->count * this->part_size + this->read_size) % this->buffer_size, size, &ptr1, &size1, &ptr2, &size2, 0);
+ err = IDirectSoundBuffer_Lock(this->dsbuffer, this->write_pos, size, &ptr1, &size1, &ptr2, &size2, 0);
/* try to restore the buffer, if necessary */
if (err == DSERR_BUFFERLOST) {
xine_log(this->class->xine, XINE_LOG_MSG, _(LOG_MODULE ": buffer lost, tryig to restore\n"));
IDirectSoundBuffer_Restore(this->dsbuffer);
- err = IDirectSoundBuffer_Lock(this->dsbuffer, (this->count * this->part_size + this->read_size) % this->buffer_size, size, &ptr1, &size1, &ptr2, &size2, 0); }
+ err = IDirectSoundBuffer_Lock(this->dsbuffer, this->write_pos, size, &ptr1, &size1, &ptr2, &size2, 0); }
if (err != DS_OK) {
audio_error(this, err, _("Couldn't lock direct sound buffer"));
return 0;
@@ -436,19 +401,15 @@ static int audio_fill(dx2_driver_t *this, char *data, size_t size) {
if (ptr1 && size1) xine_fast_memcpy(ptr1, data, size1);
if (ptr2 && size2) xine_fast_memcpy(ptr2, data + size1, size2);
- this->read_size += size;
+ // this->read_size += size;
+ this->write_pos = (this->write_pos + size ) % this->buffer_size;
+ lprintf("size %u, write_pos %u\n", size, this->write_pos);
if ((err = IDirectSoundBuffer_Unlock(this->dsbuffer, ptr1, size1, ptr2, size2)) != DS_OK) {
audio_error(this, err, _("Couldn't unlock direct sound buffer"));
return 0;
}
- /* signal, if are waiting and need wake up */
- if ((this->status == STATUS_WAIT) && buffer_ready(this)) {
- lprintf("buffer ready, waking up\n");
- pthread_cond_signal(&this->data_cond);
- }
-
return 1;
}
@@ -458,28 +419,28 @@ static int mode2channels(uint32_t mode) {
int channels;
switch(mode) {
- case AO_CAP_MODE_MONO:
- channels = 1;
- break;
-
- case AO_CAP_MODE_STEREO:
- channels = 2;
- break;
-
- case AO_CAP_MODE_4CHANNEL:
- channels = 4;
- break;
-
- case AO_CAP_MODE_5CHANNEL:
- channels = 5;
- break;
-
- case AO_CAP_MODE_5_1CHANNEL:
- channels = 6;
- break;
-
- default:
- return 0;
+ case AO_CAP_MODE_MONO:
+ channels = 1;
+ break;
+
+ case AO_CAP_MODE_STEREO:
+ channels = 2;
+ break;
+
+ case AO_CAP_MODE_4CHANNEL:
+ channels = 4;
+ break;
+
+ case AO_CAP_MODE_5CHANNEL:
+ channels = 5;
+ break;
+
+ case AO_CAP_MODE_5_1CHANNEL:
+ channels = 6;
+ break;
+
+ default:
+ return 0;
}
return channels;
@@ -506,8 +467,8 @@ static int test_capability(LPDIRECTSOUNDBUFFER buffer, uint32_t bits, uint32_t r
}
-/*
- * test capabilities of driver before opening
+/*
+ * test capabilities of driver before opening
*
* Passed only 8 bit and 16 bit with mono or stereo.
*/
@@ -556,109 +517,94 @@ static int test_capabilities(dx2_driver_t *this) {
/* size of free space in the ring buffer */
static size_t buffer_free_size(dx2_driver_t *this) {
- size_t used_full_size;
- used_full_size = this->read_size + ((this->status != STATUS_WAIT) ? this->part_size : 0);
- _x_assert(used_full_size <= this->buffer_size);
- return this->buffer_size - used_full_size;
+ int ret;
+ size_t play_pos;
+ size_t free_space;
+
+ // get current play pos
+ ret = audio_tell(this, &play_pos);
+ if (!ret)
+ return 0;
+
+ // calc free space (-1)
+ free_space = (this->buffer_size + play_pos - this->write_pos - 1) % this->buffer_size;
+
+ return free_space;
}
-/* enough data in the ring buffer for playing next part? */
-static int buffer_ready(dx2_driver_t *this) {
- return this->read_size >= this->part_size;
+/* size of occupied space in the ring buffer */
+static size_t buffer_occupied_size(dx2_driver_t *this) {
+ int ret;
+ size_t play_pos;
+ size_t used_space;
+
+ // get current play pos
+ ret = audio_tell(this, &play_pos);
+ if (!ret) return 0;
+
+ // calc used space
+ used_space = (this->buffer_size + this->write_pos - play_pos) % this->buffer_size;
+
+ return used_space;
}
/* service thread working with direct sound buffer */
static void *buffer_service(void *data) {
dx2_driver_t *this = (dx2_driver_t *)data;
- HANDLE handles[PARTS];
- DWORD ret;
- int i;
-#if defined(EXACT_SLEEP) || defined(EXACT_WAIT)
- size_t play_pos, req_delay;
-#endif
+ size_t buffer_min;
+ size_t data_in_buffer;
/* prepare empty buffer */
audio_flush(this);
- for (i = 0; i < PARTS; i++) handles[i] = this->events[i].hEventNotify;
-
+ /* prepare min buffer fill */
+ buffer_min = BUFFER_MIN_MS * this->rate / 1000 * this->frame_size;
+
/* we live! */
pthread_mutex_lock(&this->data_mutex);
pthread_cond_signal(&this->data_cond);
pthread_mutex_unlock(&this->data_mutex);
while (!this->finished) {
+
pthread_mutex_lock(&this->data_mutex);
- if (!buffer_ready(this)) {
- if (!audio_stop(this)) goto fail;
- lprintf("no data (count=%d,free=%" PRIsizet ",avail=%" PRIsizet "), sleeping...\n", this->count, buffer_free_size(this), this->read_size);
- this->status = STATUS_WAIT;
- pthread_cond_wait(&this->data_cond, &this->data_mutex);
- lprintf("wake up (count=%d,free=%" PRIsizet "--,avail=%" PRIsizet ")\n", this->count, buffer_free_size(this), this->read_size);
- if (this->finished) goto finished;
- if (!audio_seek(this, this->count * this->part_size)) goto fail;
- if (!this->paused) {
- if (!audio_play(this)) goto fail;
- }
- this->status = STATUS_RUNNING;
- this->count = (this->count + 1) % PARTS;
- this->read_size -= this->part_size;
- pthread_mutex_unlock(&this->data_mutex);
- lprintf("wait for playback (newcount=%d,free=%" PRIsizet ",avail=%" PRIsizet ")\n", this->count, buffer_free_size(this), this->read_size);
- do {
- ret = WaitForMultipleObjects(PARTS, handles, FALSE, 250) - WAIT_OBJECT_0;
+ switch( this->status){
+
+ case STATUS_WAIT:
+
+ // pre: stop/buffer flushed
+ lprintf("no data, sleeping...\n");
+ pthread_cond_wait(&this->data_cond, &this->data_mutex);
+ lprintf("woke up (write_pos=%d,free=%" PRIsizet")\n", this->write_pos, buffer_free_size(this));
if (this->finished) goto finished;
- } while (ret > PARTS);
- lprintf("playback started (newcount=%d,ev=%d,free=%" PRIsizet ",avail=%" PRIsizet ")\n", this->count, ret, buffer_free_size(this), this->read_size);
- _x_assert(ret == ((PARTS + this->count - 1) % PARTS));
- } else {
- this->count = (this->count + 1) % PARTS;
- this->read_size -= this->part_size;
- pthread_mutex_unlock(&this->data_mutex);
+ if (!audio_seek(this, 0)) goto fail;
+ if (!this->paused) {
+ if (!audio_play(this)) goto fail;
+ }
+ this->status = STATUS_RUNNING;
+ pthread_mutex_unlock(&this->data_mutex);
+ break;
+
+ case STATUS_RUNNING:
+
+ // check for buffer underrun
+ data_in_buffer = buffer_occupied_size(this);
+ if ( data_in_buffer < buffer_min){
+ xine_log(this->class->xine, XINE_LOG_MSG, _(LOG_MODULE ": play cursor overran (data %u, min %u), flushing buffers\n"),
+ data_in_buffer, buffer_min);
+ if (!audio_stop(this)) goto fail;
+ if (!audio_flush(this)) goto fail;
+ }
+ pthread_mutex_unlock(&this->data_mutex);
+
+ // just wait BUFFER_MIN_MS before next check
+ xine_usec_sleep(BUFFER_MIN_MS * 1000);
+ break;
}
- lprintf("waiting for sound event(count=%d,free=%" PRIsizet ",avail=%" PRIsizet ")...\n", this->count, buffer_free_size(this), this->read_size);
- do {
- ret = WaitForMultipleObjects(PARTS, handles, FALSE, 250) - WAIT_OBJECT_0;
- if (this->finished) goto finished;
- } while (ret > PARTS);
- lprintf("end wait(ev=%" PRIdword ",count=%d,free=%" PRIsizet ",avail=%" PRIsizet ")\n", ret, this->count, buffer_free_size(this), this->read_size);
-#ifdef PANIC_OVERRUN
- _x_abort(ret == this->count);
-#else
- if (ret != this->count) {
- xine_log(this->class->xine, XINE_LOG_MSG, _(LOG_MODULE ": play cursor overran, flushing buffers\n"));
- pthread_mutex_lock(&this->data_mutex);
- if (!audio_stop(this)) goto fail;
- if (!audio_flush(this)) goto fail;
- pthread_mutex_unlock(&this->data_mutex);
- }
-#endif
-
-#if defined(EXACT_SLEEP) || defined(EXACT_WAIT)
- /* ugly hack: wait for right time, + little over for sure */
- pthread_mutex_lock(&this->data_mutex);
- if (!audio_tell(this, &play_pos)) goto fail;
- req_delay = (this->buffer_size + play_pos - this->count * this->part_size) % this->buffer_size;
- pthread_mutex_unlock(&this->data_mutex);
- if (req_delay > (this->buffer_size >> 1)) {
- long delay;
-
- delay = 1000 * (this->buffer_size - req_delay) / (this->frame_size * this->rate) + 1 + BUFFER_MS / PARTS / 4;
- xine_log(this->class->xine, XINE_LOG_MSG, _(LOG_MODULE ": delayed by %ld msec\n"), delay);
- printf("should be delayed %ld msec\n", delay);
-#ifdef EXACT_SLEEP
- xine_usec_sleep(delay * 1000);
-#endif
-#ifdef EXACT_WAIT
- WaitForMultipleObjects(PARTS, handles, FALSE, delay);
-#endif
- }
-#endif
}
-
return NULL;
fail:
@@ -683,15 +629,15 @@ static int ao_dx2_get_property(ao_driver_t *this_gen, int property) {
switch(property) {
- case AO_PROP_MIXER_VOL:
- case AO_PROP_PCM_VOL:
- return this->volume;
+ case AO_PROP_MIXER_VOL:
+ case AO_PROP_PCM_VOL:
+ return this->volume;
- case AO_PROP_MUTE_VOL:
- return this->muted;
+ case AO_PROP_MUTE_VOL:
+ return this->muted;
- default:
- return 0;
+ default:
+ return 0;
}
}
@@ -702,26 +648,26 @@ static int ao_dx2_set_property(ao_driver_t *this_gen, int property, int value) {
switch(property) {
- case AO_PROP_MIXER_VOL:
- case AO_PROP_PCM_VOL:
- lprintf("set volume to %d\n", value);
- pthread_mutex_lock(&this->data_mutex);
- if (!this->muted) {
- if (this->dsbuffer && !audio_set_volume(this, value)) return ~value;
- }
- this->volume = value;
- pthread_mutex_unlock(&this->data_mutex);
- break;
+ case AO_PROP_MIXER_VOL:
+ case AO_PROP_PCM_VOL:
+ lprintf("set volume to %d\n", value);
+ pthread_mutex_lock(&this->data_mutex);
+ if (!this->muted) {
+ if (this->dsbuffer && !audio_set_volume(this, value)) return ~value;
+ }
+ this->volume = value;
+ pthread_mutex_unlock(&this->data_mutex);
+ break;
- case AO_PROP_MUTE_VOL:
- pthread_mutex_lock(&this->data_mutex);
- if (this->dsbuffer && !audio_set_volume(this, value ? 0 : this->volume)) return ~value;
- this->muted = value;
- pthread_mutex_unlock(&this->data_mutex);
- break;
+ case AO_PROP_MUTE_VOL:
+ pthread_mutex_lock(&this->data_mutex);
+ if (this->dsbuffer && !audio_set_volume(this, value ? 0 : this->volume)) return ~value;
+ this->muted = value;
+ pthread_mutex_unlock(&this->data_mutex);
+ break;
- default:
- return ~value;
+ default:
+ return ~value;
}
@@ -747,18 +693,17 @@ static int ao_dx2_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int
this->status = STATUS_START;
if (!audio_create_buffers(this)) return 0;
- if (!audio_create_events(this)) goto fail_buffers;
- if (!audio_set_volume(this, this->volume)) goto fail_events;
+ if (!audio_set_volume(this, this->volume)) goto fail_buffers;
if (pthread_cond_init(&this->data_cond, NULL) != 0) {
xine_log(this->class->xine, XINE_LOG_MSG, _(LOG_MODULE ": can't create pthread condition: %s\n"), strerror(errno));
- goto fail_events;
+ goto fail_buffers;
}
if (pthread_mutex_init(&this->data_mutex, NULL) != 0) {
xine_log(this->class->xine, XINE_LOG_MSG, _(LOG_MODULE ": can't create pthread mutex: %s\n"), strerror(errno));
goto fail_cond;
}
-
+
/* creating the service thread and waiting for its signal */
pthread_mutex_lock(&this->data_mutex);
if (pthread_create(&this->buffer_service, NULL, buffer_service, this) != 0) {
@@ -775,8 +720,6 @@ fail_mutex:
pthread_mutex_destroy(&this->data_mutex);
fail_cond:
pthread_cond_destroy(&this->data_cond);
-fail_events:
- audio_destroy_events(this);
fail_buffers:
audio_destroy_buffers(this);
return 0;
@@ -803,22 +746,26 @@ static int ao_dx2_bytes_per_frame(ao_driver_t *this_gen) {
static int ao_dx2_delay(ao_driver_t *this_gen) {
dx2_driver_t *this = (dx2_driver_t *)this_gen;
- int frames;
- size_t final_pos, play_pos;
-
- if (this->status != STATUS_RUNNING) return this->read_size / this->frame_size;
+ int frames = 0;
+ int ret;
+ size_t play_pos;
pthread_mutex_lock(&this->data_mutex);
- if (!audio_tell(this, &play_pos)) {
- pthread_mutex_unlock(&this->data_mutex);
- return 0;
+
+ if (this->status != STATUS_RUNNING){
+ frames = this->write_pos / this->frame_size;
+ } else {
+ ret = audio_tell(this, &play_pos);
+ if (ret){
+ frames = buffer_occupied_size(this) / this->frame_size;
+ }
}
- final_pos = this->read_size + (((PARTS + this->count - 1) % PARTS) + 1) * this->part_size - 1;
- frames = (this->buffer_size + final_pos - play_pos) % this->buffer_size / this->frame_size;
+
pthread_mutex_unlock(&this->data_mutex);
#ifdef LOG
- if ((rand() % 10) == 0) lprintf("frames=%d, play_pos=%" PRIdword ", block=%" PRIsizet "..%" PRIsizet "\n", frames, play_pos, final_pos - this->part_size + 1, final_pos);
+ if ((rand() % 10) == 0)
+ lprintf("frames=%d, play_pos=%" PRIdword ", write_pos=%u\n", frames, play_pos, this->write_pos);
#endif
return frames;
@@ -840,7 +787,7 @@ static int ao_dx2_write(ao_driver_t *this_gen, int16_t* audio_data, uint32_t num
while (((free_size = buffer_free_size(this)) == 0) && !this->finished) {
lprintf("buffer full, waiting\n");
pthread_mutex_unlock(&this->data_mutex);
- xine_usec_sleep(1000 * BUFFER_MS / PARTS / 5);
+ xine_usec_sleep(1000 * BUFFER_MS / 10);
pthread_mutex_lock(&this->data_mutex);
}
if (free_size >= input_size) size = input_size;
@@ -856,6 +803,12 @@ static int ao_dx2_write(ao_driver_t *this_gen, int16_t* audio_data, uint32_t num
input_size -= size;
}
+ /* signal, if are waiting and need wake up */
+ if ((this->status == STATUS_WAIT) && (buffer_occupied_size(this) > BUFFER_MIN_MS * this->rate / 1000 * this->frame_size)) {
+ lprintf("buffer ready, waking up\n");
+ pthread_cond_signal(&this->data_cond);
+ }
+
return 1;
}
@@ -881,7 +834,6 @@ static void ao_dx2_close(ao_driver_t *this_gen) {
if (pthread_mutex_destroy(&this->data_mutex) != 0) {
xine_log(this->class->xine, XINE_LOG_MSG, _(LOG_MODULE ": can't destroy pthread mutex: %s\n"), strerror(errno));
}
- audio_destroy_events(this);
audio_destroy_buffers(this);
}
@@ -896,12 +848,8 @@ static void ao_dx2_exit(ao_driver_t *this_gen) {
}
-/*
- * TODO: check
- */
static int ao_dx2_get_gap_tolerance(ao_driver_t *this_gen) {
- /* half of part of the buffer in pts (1 msec = 90 pts) */
- return (90 * (BUFFER_MS / PARTS)) >> 1;
+ return GAP_TOLERANCE;
}
@@ -910,36 +858,36 @@ static int ao_dx2_control(ao_driver_t *this_gen, int cmd, ...) {
switch(cmd) {
- case AO_CTRL_PLAY_PAUSE:
- lprintf("control pause\n");
- pthread_mutex_lock(&this->data_mutex);
- if (!this->paused) {
- audio_stop(this);
- this->paused = 1;
- }
- pthread_mutex_unlock(&this->data_mutex);
- break;
+ case AO_CTRL_PLAY_PAUSE:
+ lprintf("control pause\n");
+ pthread_mutex_lock(&this->data_mutex);
+ if (!this->paused) {
+ audio_stop(this);
+ this->paused = 1;
+ }
+ pthread_mutex_unlock(&this->data_mutex);
+ break;
- case AO_CTRL_PLAY_RESUME:
- lprintf("control resume\n");
- pthread_mutex_lock(&this->data_mutex);
- if (this->paused) {
- if (this->status != STATUS_WAIT) audio_play(this);
- this->paused = 0;
- }
- pthread_mutex_unlock(&this->data_mutex);
- break;
-
- case AO_CTRL_FLUSH_BUFFERS:
- lprintf("control flush\n");
- pthread_mutex_lock(&this->data_mutex);
- audio_stop(this);
- audio_flush(this);
- pthread_mutex_unlock(&this->data_mutex);
- break;
+ case AO_CTRL_PLAY_RESUME:
+ lprintf("control resume\n");
+ pthread_mutex_lock(&this->data_mutex);
+ if (this->paused) {
+ if (this->status != STATUS_WAIT) audio_play(this);
+ this->paused = 0;
+ }
+ pthread_mutex_unlock(&this->data_mutex);
+ break;
+
+ case AO_CTRL_FLUSH_BUFFERS:
+ lprintf("control flush\n");
+ pthread_mutex_lock(&this->data_mutex);
+ audio_stop(this);
+ audio_flush(this);
+ pthread_mutex_unlock(&this->data_mutex);
+ break;
- default:
- xine_log(this->class->xine, XINE_LOG_MSG, _(LOG_MODULE ": unknown control command %d\n"), cmd);
+ default:
+ xine_log(this->class->xine, XINE_LOG_MSG, _(LOG_MODULE ": unknown control command %d\n"), cmd);
}
@@ -955,7 +903,7 @@ static ao_driver_t *open_plugin(audio_driver_class_t *class_gen, const void *dat
lprintf("open plugin called\n");
- this = (dx2_driver_t *)xine_xmalloc(sizeof(dx2_driver_t));
+ this = calloc(1, sizeof(dx2_driver_t));
if (!this)
return NULL;
@@ -1009,7 +957,7 @@ static void *init_class(xine_t *xine, void *data) {
lprintf("init class\n");
- this = (dx2_class_t *)xine_xmalloc(sizeof(dx2_class_t));
+ this = calloc(1, sizeof(dx2_class_t));
if (!this)
return NULL;
diff --git a/src/audio_out/audio_directx_out.c b/src/audio_out/audio_directx_out.c
index 77e3e15b9..893a11976 100644
--- a/src/audio_out/audio_directx_out.c
+++ b/src/audio_out/audio_directx_out.c
@@ -1,18 +1,18 @@
-/*
+/*
* Copyright (C) 2001-2003 the xine project
- *
+ *
* This file is part of xine, a unix video player.
- *
+ *
* xine 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.
- *
+ *
* xine 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
@@ -60,9 +60,13 @@ typedef unsigned char boolean;
* the linking stage.
*****************************************************************************/
#if 1
-static const GUID IID_IDirectSoundNotify = {
+static const GUID xine_IID_IDirectSoundNotify = {
0xB0210783,0x89CD,0x11D0,{0xAF,0x08,0x00,0xA0,0xC9,0x25,0xCD,0x16}
};
+#ifdef IID_IDirectSoundNotify
+# undef IID_IDirectSoundNotify
+#endif
+#define IID_IDirectSoundNotify xine_IID_IDirectSoundNotify
#endif
@@ -77,14 +81,14 @@ typedef struct {
int capabilities;
xine_t *xine;
-
+
/* directx objects */
LPDIRECTSOUND dsobj;
LPDIRECTSOUNDBUFFER dsbuffer;
DSBCAPS dsbcaps;
LPDIRECTSOUNDNOTIFY notify;
DSBPOSITIONNOTIFY notify_events[ 2 ];
-
+
/* buffer vars */
long buffer_size;
int write_status;
@@ -92,13 +96,13 @@ typedef struct {
uint8_t prebuff[ SOUND_BUFFER_MAX ];
uint32_t prebuff_size;
-
+
/* current buffer properties */
int bits;
int rate;
int chnn;
int frsz;
-
+
/* current mixer settings */
int mute;
int volume;
@@ -114,7 +118,7 @@ typedef struct {
*
* BEGIN : Direct Sound and win32 handlers
* for xine audio output plugins.
- *
+ *
* ------------------------------------------- */
void Error( HWND hwnd, LPSTR szfmt, ... );
@@ -124,7 +128,7 @@ boolean CreateSoundBuffer( ao_directx_t * ao_directx );
void DestroySoundBuffer( ao_directx_t * ao_directx );
uint32_t FillSoundBuffer( ao_directx_t * ao_directx, int code, unsigned char * samples );
-/* Display formatted error message in
+/* Display formatted error message in
* popup message box. */
void Error( HWND hwnd, LPSTR szfmt, ... )
@@ -225,25 +229,25 @@ boolean CreateSoundBuffer( ao_directx_t * ao_directx )
* related resources */
DestroySoundBuffer( ao_directx );
-
+
/* create a secondary sound buffer */
-
- memset( &pcmwf, 0, sizeof( PCMWAVEFORMAT ) );
+
+ memset( &pcmwf, 0, sizeof( PCMWAVEFORMAT ) );
pcmwf.wBitsPerSample = ( unsigned short ) ao_directx->bits;
- pcmwf.wf.wFormatTag = WAVE_FORMAT_PCM;
+ pcmwf.wf.wFormatTag = WAVE_FORMAT_PCM;
pcmwf.wf.nChannels = ao_directx->chnn;
- pcmwf.wf.nSamplesPerSec = ao_directx->rate;
+ pcmwf.wf.nSamplesPerSec = ao_directx->rate;
pcmwf.wf.nBlockAlign = ao_directx->frsz;
- pcmwf.wf.nAvgBytesPerSec = ao_directx->rate * ao_directx->frsz;
+ pcmwf.wf.nAvgBytesPerSec = ao_directx->rate * ao_directx->frsz;
- memset( &dsbdesc, 0, sizeof( DSBUFFERDESC ) );
- dsbdesc.dwSize = sizeof( DSBUFFERDESC );
- dsbdesc.dwFlags = (DSBCAPS_CTRLVOLUME | DSBCAPS_GLOBALFOCUS |
+ memset( &dsbdesc, 0, sizeof( DSBUFFERDESC ) );
+ dsbdesc.dwSize = sizeof( DSBUFFERDESC );
+ dsbdesc.dwFlags = (DSBCAPS_CTRLVOLUME | DSBCAPS_GLOBALFOCUS |
DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY);
dsbdesc.dwBufferBytes = ao_directx->buffer_size;
dsbdesc.lpwfxFormat = ( LPWAVEFORMATEX ) &pcmwf;
- if( IDirectSound_CreateSoundBuffer( ao_directx->dsobj, &dsbdesc,
+ if( IDirectSound_CreateSoundBuffer( ao_directx->dsobj, &dsbdesc,
&ao_directx->dsbuffer, 0 ) != DS_OK )
{
Error( 0, "IDirectSound_CreateSoundBuffer : Unable to create secondary sound buffer" );
@@ -278,7 +282,7 @@ boolean CreateSoundBuffer( ao_directx_t * ao_directx )
/* get the direct sound notification interface */
if( IDirectSoundBuffer_QueryInterface( ao_directx->dsbuffer,
- &IID_IDirectSoundNotify,
+ &IID_IDirectSoundNotify,
(LPVOID *)&ao_directx->notify ) != DS_OK )
{
Error( 0, "IDirectSoundBuffer_QueryInterface : Unable to get notification interface" );
@@ -376,9 +380,9 @@ uint32_t FillSoundBuffer( ao_directx_t * ao_directx, int code, unsigned char * s
#ifdef LOG
if ((void*)samples != (void*)0)
- printf("audio_directx_out: FillSoundBuffer(%08x, %d, Null) Enter\n", (unsigned long)ao_directx, code);
+ printf("audio_directx_out: FillSoundBuffer(%08x, %d, Null) Enter\n", (unsigned long)ao_directx, code);
else
- printf("audio_directx_out: FillSoundBuffer(%08x, %d, Null) Enter\n", (unsigned long)ao_directx, code);
+ printf("audio_directx_out: FillSoundBuffer(%08x, %d, Null) Enter\n", (unsigned long)ao_directx, code);
#endif
half_size = ao_directx->buffer_size / 2;
@@ -481,7 +485,7 @@ uint32_t FillSoundBuffer( ao_directx_t * ao_directx, int code, unsigned char * s
}
/* write data to our sound buffer */
-
+
memcpy( buff_pointer, samples, buff_length );
/* unlock our sound buffer */
@@ -508,7 +512,7 @@ uint32_t FillSoundBuffer( ao_directx_t * ao_directx, int code, unsigned char * s
* ----------------------------------------- */
static int ao_directx_control(ao_driver_t *this_gen, int cmd, ...) {
- switch (cmd)
+ switch (cmd)
{
case AO_CTRL_PLAY_PAUSE:
@@ -535,7 +539,7 @@ static int ao_directx_open( ao_driver_t * ao_driver, uint32_t bits, uint32_t rat
ao_directx->bits = bits;
ao_directx->rate = rate;
-
+
/* store channel count */
switch( mode )
@@ -624,7 +628,7 @@ static int ao_directx_write( ao_driver_t * ao_driver, int16_t * frame_buffer, ui
uint32_t wrote; /* number of bytes written */
uint32_t half_size; /* half our sound buffer size */
- lprintf("ao_directx_write(%08x, %08x, %d) Enter\n",
+ lprintf("ao_directx_write(%08x, %08x, %d) Enter\n",
(unsigned long)ao_directx, (unsigned long)frame_buffer, num_frames);
/* zero write counter */
@@ -741,7 +745,7 @@ static int ao_directx_set_property( ao_driver_t * ao_driver, int property, int v
{
ao_directx_t *ao_directx = ( ao_directx_t * ) ao_driver;
- lprintf("ao_directx_set_property(%08x, %d, %d) Enter\n",
+ lprintf("ao_directx_set_property(%08x, %d, %d) Enter\n",
(unsigned long)ao_directx, property, value);
switch( property )
@@ -755,7 +759,7 @@ static int ao_directx_set_property( ao_driver_t * ao_driver, int property, int v
if( !ao_directx->mute && ao_directx->dsbuffer )
IDirectSoundBuffer_SetVolume( ao_directx->dsbuffer, ao_directx->volume );
- xprintf(ao_directx->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(ao_directx->xine, XINE_VERBOSITY_DEBUG,
"ao_directx : volume set to %d - directX volume = %d\n", value, ao_directx->volume);
return value;
@@ -789,11 +793,11 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da
{
audiox_class_t *class = (audiox_class_t *) class_gen;
ao_directx_t *ao_directx;
-
- ao_directx = ( ao_directx_t * ) xine_xmalloc( sizeof( ao_directx_t ) );
+
+ ao_directx = calloc(1, sizeof(ao_directx_t));
if (!ao_directx)
return NULL;
-
+
lprintf("open_plugin(%08x, %08x) Enter\n", (unsigned long)class_gen, (unsigned long)data);
lprintf("open_plugin: ao_directx=%08x\n", (unsigned long)ao_directx);
@@ -841,10 +845,10 @@ static void *init_class (xine_t *xine, void *data) {
/*
* from this point on, nothing should go wrong anymore
*/
- audiox = (audiox_class_t *) xine_xmalloc (sizeof (audiox_class_t));
+ audiox = calloc(1, sizeof (audiox_class_t));
if (!audiox)
return NULL;
-
+
audiox->driver_class.open_plugin = open_plugin;
audiox->driver_class.get_identifier = get_identifier;
audiox->driver_class.get_description = get_description;
@@ -854,7 +858,7 @@ static void *init_class (xine_t *xine, void *data) {
audiox->config = xine->config;
lprintf("init_class() Exit! Returning audiox=%08x\n", audiox);
-
+
return audiox;
}
@@ -866,7 +870,7 @@ static const ao_info_t ao_info_directx = {
* exported plugin catalog entry
*/
const plugin_info_t xine_plugin_info[] EXPORTED = {
- /* type, API, "name", version, special_info, init_function */
+ /* type, API, "name", version, special_info, init_function */
{ PLUGIN_AUDIO_OUT, AO_DIRECTX_IFACE_VERSION, "directx", XINE_VERSION_CODE, &ao_info_directx, init_class },
{ PLUGIN_NONE, 0, "", 0, NULL, NULL }
};
diff --git a/src/audio_out/audio_esd_out.c b/src/audio_out/audio_esd_out.c
index 4b209bea1..ae7576259 100644
--- a/src/audio_out/audio_esd_out.c
+++ b/src/audio_out/audio_esd_out.c
@@ -1,18 +1,18 @@
-/*
+/*
* Copyright (C) 2000-2003 the xine project
- *
+ *
* This file is part of xine, a free video player.
- *
+ *
* xine 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.
- *
+ *
* xine 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
@@ -77,7 +77,7 @@ typedef struct esd_driver_s {
/*
* Temporary sample buffer used to reblock the sample output stream
* to writes using buffer sizes of n*ESD_BUF_SIZE bytes.
- *
+ *
* The reblocking avoids a bug with esd 0.2.18 servers and reduces
* cpu load with newer versions of the esd server.
*
@@ -99,7 +99,7 @@ typedef struct {
/*
- * connect to esd
+ * connect to esd
*/
static int ao_esd_open(ao_driver_t *this_gen,
uint32_t bits, uint32_t rate, int mode)
@@ -107,7 +107,7 @@ static int ao_esd_open(ao_driver_t *this_gen,
esd_driver_t *this = (esd_driver_t *) this_gen;
esd_format_t format;
- xprintf (this->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG,
"audio_esd_out: ao_open bits=%d rate=%d, mode=%d\n", bits, rate, mode);
if ( (mode & this->capabilities) == 0 ) {
@@ -117,12 +117,12 @@ static int ao_esd_open(ao_driver_t *this_gen,
if (this->audio_fd>=0) {
- if ( (mode == this->mode) && (rate == this->input_sample_rate) )
+ if ( (mode == this->mode) && (rate == this->input_sample_rate) )
return this->output_sample_rate;
esd_close (this->audio_fd);
}
-
+
this->mode = mode;
this->input_sample_rate = rate;
this->output_sample_rate = rate;
@@ -170,7 +170,7 @@ static int ao_esd_open(ao_driver_t *this_gen,
return this->output_sample_rate;
}
-static int ao_esd_num_channels(ao_driver_t *this_gen)
+static int ao_esd_num_channels(ao_driver_t *this_gen)
{
esd_driver_t *this = (esd_driver_t *) this_gen;
return this->num_channels;
@@ -200,14 +200,14 @@ static int ao_esd_delay(ao_driver_t *this_gen)
frames += (tv.tv_sec - this->start_time.tv_sec)
* this->output_sample_rate;
- frames -= this->latency;
+ frames -= this->latency;
if (frames < 0)
frames = 0;
-
+
/* calc delay */
-
+
bytes_left = this->bytes_in_buffer - frames * this->bytes_per_frame;
-
+
if (bytes_left<=0) /* buffer ran dry */
bytes_left = 0;
return bytes_left / this->bytes_per_frame;
@@ -230,18 +230,18 @@ static int ao_esd_write(ao_driver_t *this_gen,
/* check if simulated buffer ran dry */
gettimeofday(&tv, NULL);
-
+
frames = (tv.tv_usec - this->start_time.tv_usec)
* this->output_sample_k_rate / 1000;
frames += (tv.tv_sec - this->start_time.tv_sec)
* this->output_sample_rate;
-
- frames -= this->latency;
+
+ frames -= this->latency;
if (frames < 0)
frames = 0;
/* calc delay */
-
+
simulated_bytes_in_buffer = frames * this->bytes_per_frame;
if (this->bytes_in_buffer < simulated_bytes_in_buffer)
@@ -296,7 +296,7 @@ static int ao_esd_write(ao_driver_t *this_gen,
if (nwritten != num_bytes) {
if (nwritten < 0)
xprintf(this->xine, XINE_VERBOSITY_DEBUG, "audio_esd_out: writev failed: %s\n", strerror(errno));
- else
+ else
xprintf(this->xine, XINE_VERBOSITY_DEBUG, "audio_esd_out: warning, incomplete write: %d\n", nwritten);
}
if (nwritten > 0)
@@ -337,7 +337,7 @@ static int ao_esd_get_gap_tolerance (ao_driver_t *this_gen) {
static void ao_esd_exit(ao_driver_t *this_gen)
{
esd_driver_t *this = (esd_driver_t *) this_gen;
-
+
if (this->audio_fd != -1)
esd_close(this->audio_fd);
@@ -351,19 +351,19 @@ static int ao_esd_get_property (ao_driver_t *this_gen, int property) {
int mixer_fd;
esd_player_info_t *esd_pi;
esd_info_t *esd_i;
-
+
switch(property) {
case AO_PROP_MIXER_VOL:
-
+
if((mixer_fd = esd_open_sound(NULL)) >= 0) {
if((esd_i = esd_get_all_info(mixer_fd)) != NULL) {
for(esd_pi = esd_i->player_list; esd_pi != NULL; esd_pi = esd_pi->next) {
if(!strcmp(this->pname, esd_pi->name)) {
this->mixer.source_id = esd_pi->source_id;
-
+
if(!this->mixer.mute)
- this->mixer.volume = (((esd_pi->left_vol_scale * 100) / 256) +
+ this->mixer.volume = (((esd_pi->left_vol_scale * 100) / 256) +
((esd_pi->right_vol_scale * 100) / 256)) >> 1;
}
@@ -372,7 +372,7 @@ static int ao_esd_get_property (ao_driver_t *this_gen, int property) {
}
esd_close(mixer_fd);
}
-
+
return this->mixer.volume;
break;
@@ -390,39 +390,39 @@ static int ao_esd_set_property (ao_driver_t *this_gen, int property, int value)
switch(property) {
case AO_PROP_MIXER_VOL:
-
+
if(!this->mixer.mute) {
-
+
/* need this to get source_id */
(void) ao_esd_get_property(&this->ao_driver, AO_PROP_MIXER_VOL);
if((mixer_fd = esd_open_sound(NULL)) >= 0) {
int v = (value * 256) / 100;
-
+
esd_set_stream_pan(mixer_fd, this->mixer.source_id, v, v);
-
+
if(!this->mixer.mute)
this->mixer.volume = value;
-
+
esd_close(mixer_fd);
}
}
else
this->mixer.volume = value;
-
+
return this->mixer.volume;
break;
-
+
case AO_PROP_MUTE_VOL: {
int mute = (value) ? 1 : 0;
-
+
/* need this to get source_id */
(void) ao_esd_get_property(&this->ao_driver, AO_PROP_MIXER_VOL);
-
+
if(mute) {
if((mixer_fd = esd_open_sound(NULL)) >= 0) {
int v = 0;
-
+
esd_set_stream_pan(mixer_fd, this->mixer.source_id, v, v);
esd_close(mixer_fd);
}
@@ -430,14 +430,14 @@ static int ao_esd_set_property (ao_driver_t *this_gen, int property, int value)
else {
if((mixer_fd = esd_open_sound(NULL)) >= 0) {
int v = (this->mixer.volume * 256) / 100;
-
+
esd_set_stream_pan(mixer_fd, this->mixer.source_id, v, v);
esd_close(mixer_fd);
}
}
-
+
this->mixer.mute = mute;
-
+
return value;
}
break;
@@ -465,7 +465,7 @@ static int ao_esd_ctrl(ao_driver_t *this_gen, int cmd, ...) {
return 0;
}
-static ao_driver_t *open_plugin (audio_driver_class_t *class_gen,
+static ao_driver_t *open_plugin (audio_driver_class_t *class_gen,
const void *data) {
esd_class_t *class = (esd_class_t *) class_gen;
@@ -491,7 +491,7 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen,
sigemptyset(&vo_mask);
sigaddset(&vo_mask, SIGALRM);
- if (sigprocmask(SIG_UNBLOCK, &vo_mask, &vo_mask_orig))
+ if (sigprocmask(SIG_UNBLOCK, &vo_mask, &vo_mask_orig))
xprintf(class->xine, XINE_VERBOSITY_DEBUG, "audio_esd_out: cannot unblock SIGALRM: %s\n", strerror(errno));
xprintf(class->xine, XINE_VERBOSITY_LOG, _("audio_esd_out: connecting to esd server...\n"));
@@ -511,7 +511,7 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen,
return NULL;
}
-
+
esd_svinfo = esd_get_server_info(audio_fd);
if (esd_svinfo) {
server_sample_rate = esd_svinfo->rate;
@@ -521,7 +521,7 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen,
esd_close(audio_fd);
- this = (esd_driver_t *) xine_xmalloc (sizeof (esd_driver_t));
+ this = calloc(1, sizeof (esd_driver_t));
if (!this)
return NULL;
this->xine = class->xine;
@@ -583,7 +583,7 @@ static void *init_class (xine_t *xine, void *data) {
esd_class_t *this;
- this = (esd_class_t *) xine_xmalloc (sizeof (esd_class_t));
+ this = calloc(1, sizeof (esd_class_t));
if (!this)
return NULL;
@@ -606,7 +606,7 @@ static const ao_info_t ao_info_esd = {
*/
const plugin_info_t xine_plugin_info[] EXPORTED = {
- /* type, API, "name", version, special_info, init_function */
+ /* type, API, "name", version, special_info, init_function */
{ PLUGIN_AUDIO_OUT, AO_OUT_ESD_IFACE_VERSION, "esd", XINE_VERSION_CODE, &ao_info_esd, init_class },
{ PLUGIN_NONE, 0, "", 0, NULL, NULL }
};
diff --git a/src/audio_out/audio_file_out.c b/src/audio_out/audio_file_out.c
index 225d64d0e..7b7bfe950 100644
--- a/src/audio_out/audio_file_out.c
+++ b/src/audio_out/audio_file_out.c
@@ -1,18 +1,18 @@
-/*
+/*
* Copyright (C) 2000-2003 the xine project
- *
+ *
* This file is part of xine, a free video player.
- *
+ *
* xine 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.
- *
+ *
* xine 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
@@ -46,7 +46,7 @@ struct wavhdr {
unsigned char bRiffMagic[4]; // 'RIFF'
uint32_t wRiffLength ; // length of file minus the 8 byte riff header
unsigned char bWaveMagic[8]; // 'WAVEfmt '
- uint32_t wFmtSize; // length of format chunk minus 8 byte header
+ uint32_t wFmtSize; // length of format chunk minus 8 byte header
uint16_t wFormatTag; // identifies PCM, ULAW etc
uint16_t wChannels;
uint32_t dwSamplesPerSecond; // samples per second per channel
@@ -93,7 +93,7 @@ static int ao_file_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int
file_driver_t *this = (file_driver_t *) this_gen;
struct wavhdr w;
- xprintf (this->xine, XINE_VERBOSITY_LOG,
+ xprintf (this->xine, XINE_VERBOSITY_LOG,
"audio_file_out: ao_open bits=%d rate=%d, mode=%d\n", bits, rate, mode);
this->mode = mode;
@@ -314,7 +314,7 @@ static int ao_file_ctrl(ao_driver_t *this_gen, int cmd, ...) {
return 0;
}
-static ao_driver_t *open_plugin (audio_driver_class_t *class_gen,
+static ao_driver_t *open_plugin (audio_driver_class_t *class_gen,
const void *data) {
file_class_t *class = (file_class_t *) class_gen;
@@ -323,7 +323,7 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen,
lprintf ("open_plugin called\n");
- this = (file_driver_t *) xine_xmalloc (sizeof (file_driver_t));
+ this = calloc(1, sizeof (file_driver_t));
if (!this)
return NULL;
@@ -375,7 +375,7 @@ static void *init_class (xine_t *xine, void *data) {
lprintf ("init class\n");
- this = (file_class_t *) xine_xmalloc (sizeof (file_class_t));
+ this = calloc(1, sizeof (file_class_t));
if (!this)
return NULL;
@@ -399,7 +399,7 @@ static const ao_info_t ao_info_file = {
*/
const plugin_info_t xine_plugin_info[] EXPORTED = {
- /* type, API, "name", version, special_info, init_function */
+ /* type, API, "name", version, special_info, init_function */
{ PLUGIN_AUDIO_OUT, AO_OUT_FILE_IFACE_VERSION, "file", XINE_VERSION_CODE, &ao_info_file, init_class },
{ PLUGIN_NONE, 0, "", 0, NULL, NULL }
};
diff --git a/src/audio_out/audio_fusionsound_out.c b/src/audio_out/audio_fusionsound_out.c
index 92eadc6cf..873ab32e9 100644
--- a/src/audio_out/audio_fusionsound_out.c
+++ b/src/audio_out/audio_fusionsound_out.c
@@ -1,13 +1,13 @@
/*
* Copyright (C) 2000-2006 the xine project and Claudio Ciccani
- *
+ *
* This file is part of xine, a free video player.
- *
+ *
* xine 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.
- *
+ *
* xine 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
@@ -69,10 +69,10 @@ typedef struct fusionsound_driver_s {
float vol;
int vol_mute;
-
+
float amp;
int amp_mute;
-
+
int paused;
} fusionsound_driver_t;
@@ -90,12 +90,12 @@ static int ao_fusionsound_open(ao_driver_t *ao_driver,
DFBResult ret;
lprintf ("ao_open( bits=%d, rate=%d, mode=%d )\n", bits, rate, mode);
-
- dsc.flags = FSSDF_BUFFERSIZE | FSBDF_CHANNELS |
+
+ dsc.flags = FSSDF_BUFFERSIZE | FSBDF_CHANNELS |
FSSDF_SAMPLEFORMAT | FSSDF_SAMPLERATE;
switch (mode) {
- case AO_CAP_MODE_MONO:
+ case AO_CAP_MODE_MONO:
dsc.channels = 1;
break;
case AO_CAP_MODE_STEREO:
@@ -140,13 +140,13 @@ static int ao_fusionsound_open(ao_driver_t *ao_driver,
this->playback->Release (this->playback);
this->playback = NULL;
}
-
+
if (this->stream) {
this->stream->Release (this->stream);
this->stream = NULL;
}
-
- ret = this->sound->CreateStream (this->sound, &dsc, &this->stream);
+
+ ret = this->sound->CreateStream (this->sound, &dsc, &this->stream);
if (ret != DFB_OK) {
xprintf (this->xine, XINE_VERBOSITY_LOG,
"audio_fusionsound_out: IFusionSound::CreateStream() failed [%s]\n",
@@ -160,10 +160,10 @@ static int ao_fusionsound_open(ao_driver_t *ao_driver,
this->channels = dsc.channels;
this->rate = dsc.samplerate;
this->bytes_per_frame = this->channels * FS_BYTES_PER_SAMPLE(this->format);
-
+
ret = this->stream->GetPlayback (this->stream, &this->playback);
if (ret == DFB_OK) {
- this->playback->SetVolume (this->playback,
+ this->playback->SetVolume (this->playback,
(this->vol_mute ? 0 : this->vol) *
(this->amp_mute ? 0 : this->amp));
if (this->paused)
@@ -182,22 +182,22 @@ static int ao_fusionsound_open(ao_driver_t *ao_driver,
static int ao_fusionsound_num_channels(ao_driver_t *ao_driver) {
fusionsound_driver_t *this = (fusionsound_driver_t *) ao_driver;
-
+
return this->channels;
}
static int ao_fusionsound_bytes_per_frame(ao_driver_t *ao_driver) {
fusionsound_driver_t *this = (fusionsound_driver_t *) ao_driver;
-
+
return this->bytes_per_frame;
}
static int ao_fusionsound_delay(ao_driver_t *ao_driver) {
fusionsound_driver_t *this = (fusionsound_driver_t *) ao_driver;
int delay = 0;
-
+
this->stream->GetPresentationDelay (this->stream, &delay);
-
+
return (delay * this->rate / 1000);
}
@@ -209,7 +209,7 @@ static int ao_fusionsound_write(ao_driver_t *ao_driver,
int16_t *data, uint32_t num_frames) {
fusionsound_driver_t *this = (fusionsound_driver_t *) ao_driver;
DFBResult ret;
-
+
if (this->paused) {
xprintf (this->xine, XINE_VERBOSITY_DEBUG,
"audio_fusionsound_out: "
@@ -226,7 +226,7 @@ static int ao_fusionsound_write(ao_driver_t *ao_driver,
FusionSoundErrorString (ret));
return 0;
}
-
+
return num_frames;
}
@@ -264,13 +264,13 @@ static void ao_fusionsound_exit(ao_driver_t *ao_driver) {
if (this->playback)
this->playback->Release (this->playback);
-
+
if (this->stream)
this->stream->Release (this->stream);
if (this->sound)
this->sound->Release (this->sound);
-
+
free (this);
}
@@ -287,17 +287,17 @@ static int ao_fusionsound_get_property(ao_driver_t *ao_driver, int property) {
xprintf (this->xine, XINE_VERBOSITY_DEBUG,
"audio_fusionsound_out: volume mute is %d\n", this->vol_mute);
return this->vol_mute;
-
+
case AO_PROP_AMP:
xprintf (this->xine, XINE_VERBOSITY_DEBUG,
"audio_fusionsound_out: amplifier is %.2f\n", this->amp);
return (int) (this->amp * 100.0);
-
+
case AO_PROP_AMP_MUTE:
xprintf (this->xine, XINE_VERBOSITY_DEBUG,
"audio_fusionsound_out: amplifier mute is %d\n", this->amp_mute);
return this->amp_mute;
-
+
default:
break;
}
@@ -305,10 +305,10 @@ static int ao_fusionsound_get_property(ao_driver_t *ao_driver, int property) {
return 0;
}
-static int ao_fusionsound_set_property(ao_driver_t *ao_driver,
+static int ao_fusionsound_set_property(ao_driver_t *ao_driver,
int property, int value ) {
fusionsound_driver_t *this = (fusionsound_driver_t *) ao_driver;
-
+
if (!this->playback)
return 0;
@@ -318,11 +318,11 @@ static int ao_fusionsound_set_property(ao_driver_t *ao_driver,
xprintf (this->xine, XINE_VERBOSITY_DEBUG,
"audio_fusionsound_out: volume set to %.2f\n", this->vol);
break;
-
+
case AO_PROP_MUTE_VOL:
this->vol_mute = value ? 1 : 0;
xprintf (this->xine, XINE_VERBOSITY_DEBUG,
- "audio_fusionsound_out: volume mute set to %d\n",
+ "audio_fusionsound_out: volume mute set to %d\n",
this->vol_mute);
break;
@@ -331,20 +331,20 @@ static int ao_fusionsound_set_property(ao_driver_t *ao_driver,
xprintf (this->xine, XINE_VERBOSITY_DEBUG,
"audio_fusionsound_out: amplifier set to %.2f\n", this->amp);
break;
-
+
case AO_PROP_AMP_MUTE:
this->amp_mute = value ? 1 : 0;
xprintf (this->xine, XINE_VERBOSITY_DEBUG,
- "audio_fusionsound_out: amplifier mute set to %d\n",
+ "audio_fusionsound_out: amplifier mute set to %d\n",
this->amp_mute);
break;
default:
return 0;
}
-
+
if (this->playback) {
- this->playback->SetVolume (this->playback,
+ this->playback->SetVolume (this->playback,
(this->vol_mute ? 0 : this->vol) *
(this->amp_mute ? 0 : this->amp));
}
@@ -362,10 +362,10 @@ static int ao_fusionsound_control(ao_driver_t *ao_driver, int cmd, ...) {
this->playback->Stop (this->playback);
this->paused = 1;
return 1;
-
+
case AO_CTRL_PLAY_RESUME:
lprintf ("Resume()\n");
- if (this->playback)
+ if (this->playback)
this->playback->Continue (this->playback);
this->paused = 0;
return 1;
@@ -384,16 +384,16 @@ static int ao_fusionsound_control(ao_driver_t *ao_driver, int cmd, ...) {
}
-static ao_driver_t* open_plugin(audio_driver_class_t *ao_class,
+static ao_driver_t* open_plugin(audio_driver_class_t *ao_class,
const void *data ) {
fusionsound_class_t *class = (fusionsound_class_t *) ao_class;
fusionsound_driver_t *this;
const char *args[] = { "xine", "--dfb:no-sighandler", "--fs:no-banner" };
- int argn = sizeof(args) / sizeof(args[0]);
+ const size_t argn = sizeof(args) / sizeof(args[0]);
char **argp = (char **) args;
DFBResult ret;
- this = (fusionsound_driver_t *) xine_xmalloc (sizeof(fusionsound_driver_t));
+ this = calloc(1, sizeof(fusionsound_driver_t));
if (!this) {
xprintf (class->xine, XINE_VERBOSITY_LOG,
"audio_fusionsound_out: driver interface allocation failed!\n");
@@ -424,7 +424,7 @@ static ao_driver_t* open_plugin(audio_driver_class_t *ao_class,
this->ao_driver.exit = ao_fusionsound_exit;
this->ao_driver.get_gap_tolerance = ao_fusionsound_get_gap_tolerance;
this->ao_driver.control = ao_fusionsound_control;
-
+
this->vol = this->amp = 1.0;
return &this->ao_driver;
@@ -449,7 +449,7 @@ static void dispose_class(audio_driver_class_t *ao_class) {
static void* init_class(xine_t *xine, void *data) {
fusionsound_class_t *class;
const char *error;
-
+
/* check FusionSound version */
error = FusionSoundCheckVersion( FUSIONSOUND_MAJOR_VERSION,
FUSIONSOUND_MINOR_VERSION,
@@ -460,7 +460,7 @@ static void* init_class(xine_t *xine, void *data) {
return NULL;
}
- class = (fusionsound_class_t *) xine_xmalloc (sizeof( fusionsound_class_t));
+ class = calloc(1, sizeof( fusionsound_class_t));
if (!class) {
xprintf (xine, XINE_VERBOSITY_LOG,
"audio_fusionsound_out: class interface allocation failed!\n");
@@ -485,7 +485,7 @@ static const ao_info_t ao_info_fusionsound = {
*/
const plugin_info_t xine_plugin_info[] EXPORTED = {
- /* type, API, "name", version, special_info, init_function */
+ /* type, API, "name", version, special_info, init_function */
{ PLUGIN_AUDIO_OUT, AO_OUT_FS_IFACE_VERSION, "FusionSound",
XINE_VERSION_CODE, &ao_info_fusionsound, init_class },
{ PLUGIN_NONE, 0, "", 0, NULL, NULL }
diff --git a/src/audio_out/audio_irixal_out.c b/src/audio_out/audio_irixal_out.c
index 1654cc1a7..336996a99 100644
--- a/src/audio_out/audio_irixal_out.c
+++ b/src/audio_out/audio_irixal_out.c
@@ -1,18 +1,18 @@
-/*
+/*
* Copyright (C) 2000-2003 the xine project
- *
+ *
* This file is part of xine, a free video player.
- *
+ *
* xine 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.
- *
+ *
* xine 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
@@ -113,7 +113,7 @@ static int ao_irixal_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, i
default:
xlerror ("irixal Driver does not support the requested mode: 0x%x",mode);
return 0;
- }
+ }
if (! (config = alNewConfig ()))
{
@@ -126,7 +126,7 @@ static int ao_irixal_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, i
alFreeConfig (config);
return 0;
}
-
+
switch (bits) {
case 8:
if ( (alSetWidth (config, AL_SAMPLE_8)) == -1)
@@ -211,7 +211,7 @@ static int ao_irixal_get_gap_tolerance (ao_driver_t *this_gen)
return this->gap_tolerance;
}
-static int ao_irixal_delay (ao_driver_t *this_gen)
+static int ao_irixal_delay (ao_driver_t *this_gen)
{
irixal_driver_t *this = (irixal_driver_t *) this_gen;
stamp_t stamp, time;
@@ -230,7 +230,7 @@ static int ao_irixal_write(ao_driver_t *this_gen,int16_t *data, uint32_t num_fra
{
irixal_driver_t *this = (irixal_driver_t *) this_gen;
stamp_t stamp;
-
+
/* Grmbf. IRIX audio does not tell us, wenn we run dry.
* We have to detect this ourself. */
/* get absolute number of samples played so far
@@ -249,7 +249,7 @@ static int ao_irixal_write(ao_driver_t *this_gen,int16_t *data, uint32_t num_fra
* alGetFillable() would tell us, whether space was available */
alWriteFrames (this->port, data, num_frames);
this->frames_in_buffer += num_frames;
-
+
return num_frames;
}
@@ -376,9 +376,9 @@ static void *init_audio_out_plugin (config_values_t *config)
}
}
}
-
+
printf (" capabilities 0x%X\n",this->capabilities);
-
+
/* TODO: anything can change during runtime... move check to the right location */
this->gap_tolerance = config->register_range (config, "audio.device.irixal_gap_tolerance",
DEFAULT_GAP_TOLERANCE, 0, 90000,
@@ -396,7 +396,7 @@ static void *init_audio_out_plugin (config_values_t *config)
this->ao_driver.num_channels = ao_irixal_num_channels;
this->ao_driver.bytes_per_frame = ao_irixal_bytes_per_frame;
this->ao_driver.delay = ao_irixal_delay;
- this->ao_driver.write = ao_irixal_write;
+ this->ao_driver.write = ao_irixal_write;
this->ao_driver.close = ao_irixal_close;
this->ao_driver.exit = ao_irixal_exit;
this->ao_driver.get_gap_tolerance = ao_irixal_get_gap_tolerance;
@@ -421,7 +421,7 @@ ao_info_t *get_audio_out_plugin_info()
*/
const plugin_info_t xine_plugin_info[] EXPORTED = {
- /* type, API, "name", version, special_info, init_function */
+ /* type, API, "name", version, special_info, init_function */
{ PLUGIN_AUDIO_OUT, AO_OUT_IRIXAL_IFACE_VERSION, "irixal", XINE_VERSION_CODE, &ao_info_irixal, init_audio_out_plugin },
{ PLUGIN_NONE, 0, "", 0, NULL, NULL }
};
diff --git a/src/audio_out/audio_jack_out.c b/src/audio_out/audio_jack_out.c
index 1bc070527..a343310f0 100644
--- a/src/audio_out/audio_jack_out.c
+++ b/src/audio_out/audio_jack_out.c
@@ -1,3 +1,6 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
#include <stdio.h>
#include <errno.h>
@@ -17,431 +20,926 @@
#define AO_OUT_JACK_IFACE_VERSION 8
#define GAP_TOLERANCE AO_MAX_GAP
-#define BUFSIZE 81920
+/* maximum number of channels supported, avoids lots of mallocs */
+#define MAX_CHANS 6
-typedef struct jack_driver_s {
+typedef struct jack_driver_s
+{
+ ao_driver_t ao_driver;
+ xine_t *xine;
+
+ int capabilities;
+ int mode;
+ int paused;
+ int underrun;
+
+ int32_t output_sample_rate, input_sample_rate;
+ uint32_t num_channels;
+ uint32_t bits_per_sample;
+ uint32_t bytes_per_frame;
+ uint32_t bytes_in_buffer; /* number of bytes writen to audio hardware */
+ uint32_t fragment_size;
+
+ jack_client_t *client;
+ jack_port_t *ports[MAX_CHANS];
+
+ /*! buffer for audio data */
+ unsigned char *buffer;
+
+ /*! buffer read position, may only be modified by playback thread or while it is stopped */
+ uint32_t read_pos;
+ /*! buffer write position, may only be modified by MPlayer's thread */
+ uint32_t write_pos;
+
+ struct
+ {
+ int volume;
+ int mute;
+ } mixer;
- ao_driver_t ao_driver;
- xine_t *xine;
+} jack_driver_t;
- int capabilities;
+typedef struct
+{
+ audio_driver_class_t driver_class;
+ config_values_t *config;
+ xine_t *xine;
+} jack_class_t;
- int32_t sample_rate;
- uint32_t num_channels;
- uint32_t bits_per_sample;
- uint32_t bytes_per_frame;
- jack_client_t *client;
- jack_port_t *port_1;
- jack_port_t *port_2;
- float buf_1[BUFSIZE];
- float buf_2[BUFSIZE];
- uint32_t buf_read;
- uint32_t buf_write;
+/**************************************************************
+ *
+ * Simple ringbuffer implementation
+ * Lifted from mplayer ao_jack.c
+ *
+**************************************************************/
+
+
+/*! size of one chunk, if this is too small Xine will start to "stutter" */
+/*! after a short time of playback */
+#define CHUNK_SIZE (16 * 1024)
+/*! number of "virtual" chunks the buffer consists of */
+#define NUM_CHUNKS 8
+/* This type of ring buffer may never fill up completely, at least */
+/* one byte must always be unused. */
+/* For performance reasons (alignment etc.) one whole chunk always stays */
+/* empty, not only one byte. */
+#define BUFFSIZE ((NUM_CHUNKS + 1) * CHUNK_SIZE)
+
+/**
+ * \brief get the number of free bytes in the buffer
+ * \return number of free bytes in buffer
+ *
+ * may only be called by Xine's thread
+ * return value may change between immediately following two calls,
+ * and the real number of free bytes might be larger!
+ */
+static int buf_free (jack_driver_t *this)
+{
+ int free = this->read_pos - this->write_pos - CHUNK_SIZE;
+ if (free < 0)
+ free += BUFFSIZE;
+ return free;
+}
- uint32_t volume;
- uint32_t mute;
+/**
+ * \brief get amount of data available in the buffer
+ * \return number of bytes available in buffer
+ *
+ * may only be called by the playback thread
+ * return value may change between immediately following two calls,
+ * and the real number of buffered bytes might be larger!
+ */
+static int buf_used (jack_driver_t *this)
+{
+ int used = this->write_pos - this->read_pos;
+ if (used < 0)
+ used += BUFFSIZE;
+ return used;
+}
-} jack_driver_t;
+/**
+ * \brief insert len bytes into buffer
+ * \param data data to insert
+ * \param len length of data
+ * \return number of bytes inserted into buffer
+ *
+ * If there is not enough room, the buffer is filled up
+ *
+ * TODO: Xine should really pass data as float, perhaps in V1.2?
+ */
+static int write_buffer_32 (jack_driver_t *this, unsigned char *data, int len)
+{
+ int first_len = BUFFSIZE - this->write_pos;
+ int free = buf_free (this);
+ if (len > free)
+ len = free;
+ if (first_len > len)
+ first_len = len;
+
+ /* copy from current write_pos to end of buffer */
+ memcpy (&(this->buffer[this->write_pos]), data, first_len);
+ if (len > first_len) { /* we have to wrap around */
+ /* remaining part from beginning of buffer */
+ memcpy (this->buffer, &data[first_len], len - first_len);
+ }
+ this->write_pos = (this->write_pos + len) % BUFFSIZE;
+
+ return len;
+}
+
+static int write_buffer_16 (jack_driver_t *this, unsigned char *data, int len)
+{
+ int samples_free = buf_free (this) / (sizeof (float));
+ int samples = len / 2;
+ if (samples > samples_free)
+ samples = samples_free;
+
+ /* Rename some pointers so that the next bit of gymnastics is easier to read */
+ uint32_t write_pos = this->write_pos;
+ float *p_write;
+ int16_t *p_read = (int16_t *) data;
+ int i;
+ for (i = 0; i < samples; i++) {
+ /* Read in 16bits, write out floats */
+ p_write = (float *) (&(this->buffer[write_pos]));
+ *p_write = ((float) (p_read[i])) / 32768.0f;
+ write_pos = (write_pos + sizeof (float)) % BUFFSIZE;
+ }
+ this->write_pos = write_pos;
+
+ return samples * 2;
+}
-typedef struct {
- audio_driver_class_t driver_class;
- config_values_t *config;
- xine_t *xine;
-} jack_class_t;
-static int jack_process(jack_nframes_t nframes, void *arg)
+/**
+ * \brief read data from buffer and splitting it into channels
+ * \param bufs num_bufs float buffers, each will contain the data of one channel
+ * \param cnt number of samples to read per channel
+ * \param num_bufs number of channels to split the data into
+ * \return number of samples read per channel, equals cnt unless there was too
+ * little data in the buffer
+ *
+ * Assumes the data in the buffer is of type float, the number of bytes
+ * read is res * num_bufs * sizeof(float), where res is the return value.
+ * If there is not enough data in the buffer remaining parts will be filled
+ * with silence.
+ */
+static int read_buffer (jack_driver_t *this, float **bufs, int cnt,
+ int num_bufs, float gain)
{
- jack_driver_t *this = (jack_driver_t *)arg;
- uint32_t local_buf_read = this->buf_read;
- uint32_t local_buf_write = this->buf_write;
- uint32_t src_channel, target_channel;
- uint32_t frame;
- float *buf, *out;
- float gain = 0;
-
- if (!this->client) return 0;
-
- if (!this->mute) {
- gain = (float)this->volume / 100.0;
+ int buffered = buf_used (this);
+ int i, j;
+ int orig_cnt = cnt;
+ if (cnt * sizeof (float) * num_bufs > buffered)
+ cnt = buffered / (sizeof (float) * num_bufs);
+
+ uint32_t read_pos = this->read_pos;
+ unsigned char *buffer = this->buffer;
+ for (i = 0; i < cnt; i++) {
+ for (j = 0; j < num_bufs; j++) {
+ bufs[j][i] = *((float *) (&(buffer[read_pos]))) * gain;
+ read_pos = (read_pos + sizeof (float)) % BUFFSIZE;
}
+ }
+ this->read_pos = read_pos;
+ for (i = cnt; i < orig_cnt; i++)
+ for (j = 0; j < num_bufs; j++)
+ bufs[j][i] = 0;
- for (target_channel = 0; target_channel < 2; ++target_channel) {
-
- if (target_channel < this->num_channels) src_channel = target_channel;
- else src_channel = 0;
+ return cnt;
+}
- jack_port_t *port = (target_channel ? this->port_2 : this->port_1);
- if (!port) continue;
+/**
+ * \brief fill the buffers with silence
+ * \param bufs num_bufs float buffers, each will contain the data of one channel
+ * \param cnt number of samples in each buffer
+ * \param num_bufs number of buffers
+ */
+static void silence (float **bufs, int cnt, int num_bufs)
+{
+ int i, j;
+ for (i = 0; i < cnt; i++)
+ for (j = 0; j < num_bufs; j++)
+ bufs[j][i] = 0;
+}
- buf = (src_channel ? this->buf_2 : this->buf_1);
- out = (float *)jack_port_get_buffer(port, nframes);
- local_buf_read = this->buf_read;
- frame = 0;
+/**************************************************************
+ *
+ * Jack interface functions
+ *
+**************************************************************/
- while (frame < nframes && local_buf_read != local_buf_write) {
- // local_buf_write doesn't change during this process,
- // so we can safely defer updating buf_read until after
+/**
+ * \brief stop playing and empty buffers (for seeking/pause)
+ */
+static void jack_reset (jack_driver_t *this)
+{
+ this->paused = 1;
+ this->read_pos = this->write_pos = 0;
+ this->paused = 0;
+}
- out[frame++] = buf[local_buf_read] * gain;
- if (++local_buf_read == BUFSIZE) local_buf_read = 0;
- }
+static int jack_callback (jack_nframes_t nframes, void *arg)
+{
+ jack_driver_t *this = (jack_driver_t *) arg;
- if (frame < nframes) {
-// printf("jack_process: underrun: %u required, %u available\n",
-// nframes, frame);
- while (frame < nframes) {
- out[frame++] = 0.0f;
- }
- }
+ if (!this->client) {
+ xprintf (this->xine, XINE_VERBOSITY_LOG,
+ "jack_callback: called without a client parameter? silently trying to continue...\n");
+ return 0;
+ }
+
+ float gain = 0;
+ if (!this->mixer.mute) {
+ gain = (float) this->mixer.volume / 100.0;
+ gain *= gain; /* experiment with increasing volume range */
+ }
+
+ float *bufs[MAX_CHANS];
+ int i;
+ for (i = 0; i < this->num_channels; i++)
+ bufs[i] = jack_port_get_buffer (this->ports[i], nframes);
+
+ if (this->paused || this->underrun) {
+ silence (bufs, nframes, this->num_channels);
+ } else {
+ int frames_read = read_buffer (this, bufs, nframes, this->num_channels, gain);
+ if (frames_read < nframes) {
+ xprintf (this->xine, XINE_VERBOSITY_LOG,
+ "jack_callback: underrun - frames read: %d\n", frames_read);
+ this->underrun = 1;
}
+ }
- this->buf_read = local_buf_read;
+ return 0;
+}
-// printf("jack_process: buf_read %u, buf_write %u\n", this->buf_read, this->buf_write);
+static void jack_shutdown (void *arg)
+{
+ jack_driver_t *this = (jack_driver_t *) arg;
+ this->client = NULL;
+}
- return 0;
+/*
+ * Open the Jack audio device
+ * Return 1 on success, 0 on failure
+ * All error handling rests with the caller, we just try to open the device here
+ */
+static int jack_open_device (ao_driver_t *this_gen, char *jack_device,
+ int32_t *poutput_sample_rate, int num_channels)
+{
+ jack_driver_t *this = (jack_driver_t *) this_gen;
+ const char **matching_ports = NULL;
+ char *port_name = NULL;
+ jack_client_t *client = this->client;
+
+ int port_flags = JackPortIsInput;
+ int i;
+ int num_ports;
+
+ if (num_channels > MAX_CHANS) {
+ xprintf (this->xine, XINE_VERBOSITY_LOG,
+ "jack_open_device: Invalid number of channels: %i\n",
+ num_channels);
+ goto err_out;
+ }
+ /* Try to create a client called "xine[-NN]" */
+ if ((client = jack_client_open ("xine", JackNullOption, NULL)) == 0) {
+ xprintf (this->xine, XINE_VERBOSITY_LOG,
+ "\njack_open_device: Error: Failed to connect to JACK server\n");
+ goto err_out;
+ }
+
+ /* Save the new client */
+ this->client = client;
+
+ jack_reset (this);
+ jack_set_process_callback (client, jack_callback, this);
+
+ /* list matching ports */
+ if (!jack_device)
+ port_flags |= JackPortIsPhysical;
+ matching_ports = jack_get_ports (client, jack_device, NULL, port_flags);
+ for (num_ports = 0; matching_ports && matching_ports[num_ports];
+ num_ports++);
+ if (!num_ports) {
+ xprintf (this->xine, XINE_VERBOSITY_LOG,
+ "jack_open_device: no physical ports available\n");
+ goto err_out;
+ }
+ if (num_ports < num_channels) {
+ xprintf (this->xine, XINE_VERBOSITY_LOG,
+ "jack_open_device: not enough physical ports available\n");
+ goto err_out;
+ }
+
+ /* create output ports */
+ for (i = 0; i < num_channels; i++) {
+ char pname[50];
+ snprintf (pname, 50, "out_%d", i);
+ this->ports[i] =
+ jack_port_register (client, pname, JACK_DEFAULT_AUDIO_TYPE,
+ JackPortIsOutput, 0);
+ if (!this->ports[i]) {
+ xprintf (this->xine, XINE_VERBOSITY_LOG,
+ "jack_open_device: could not create output ports? Why not?\n");
+ goto err_out;
+ }
+ }
+ if (jack_activate (client)) {
+ xprintf (this->xine, XINE_VERBOSITY_LOG,
+ "jack_open_device: jack_activate() failed\n");
+ goto err_out;
+ }
+ for (i = 0; i < num_channels; i++) {
+ if (jack_connect
+ (client, jack_port_name (this->ports[i]), matching_ports[i])) {
+ xprintf (this->xine, XINE_VERBOSITY_LOG,
+ "jack_open_device: jack_connect() failed\n");
+ goto err_out;
+ }
+ }
+ *poutput_sample_rate = jack_get_sample_rate (client);
+
+ free (matching_ports);
+ return 1;
+
+err_out:
+ free (matching_ports);
+ if (client) {
+ jack_client_close (client);
+ this->client = NULL;
+ }
+ return 0;
}
-
-static void jack_shutdown(void *arg)
+
+/**************************************************************
+ *
+ * Xine interface functions
+ *
+**************************************************************/
+
+
+/**
+ * close the device and reset the play position
+ */
+static void ao_jack_close (ao_driver_t *this_gen)
{
- jack_driver_t *this = (jack_driver_t *)arg;
- this->client = 0;
+ jack_driver_t *this = (jack_driver_t *) this_gen;
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG, "ao_jack_close: closing\n");
+
+ jack_reset (this);
+ if (this->client) {
+ jack_client_close (this->client);
+ this->client = NULL;
+ }
}
/*
* open the audio device for writing to
*/
-static int ao_jack_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int mode)
+static int ao_jack_open (ao_driver_t *this_gen, uint32_t bits, uint32_t rate,
+ int mode)
{
- jack_driver_t *this = (jack_driver_t *) this_gen;
+ jack_driver_t *this = (jack_driver_t *) this_gen;
+ config_values_t *config = this->xine->config;
+ char *jack_device;
- if (bits != 16) {
- fprintf(stderr, "ao_jack_open: bits=%u expected %u\n", bits, 16);
- return 0;
- }
+ jack_device =
+ config->lookup_entry (config, "audio.device.jack_device_name")->str_value;
+
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG,
+ "ao_jack_open: ao_open rate=%d, mode=%d, bits=%d dev=%s\n", rate,
+ mode, bits, jack_device);
- rate = jack_get_sample_rate(this->client);
- fprintf(stderr, "ao_jack_open: JACK sample rate is %u\n", rate);
+ if ((bits != 16) && (bits != 32)) {
+ xprintf (this->xine, XINE_VERBOSITY_LOG,
+ "ao_jack_open: bits=%u expected 16 or 32bit only\n", bits);
+ return 0;
+ }
- switch (mode) {
- case AO_CAP_MODE_MONO:
- this->num_channels = 1;
- break;
- case AO_CAP_MODE_STEREO:
- this->num_channels = 2;
- break;
+ if ((mode & this->capabilities) == 0) {
+ xprintf (this->xine, XINE_VERBOSITY_LOG,
+ "ao_jack_open: unsupported mode %08x\n", mode);
+ return 0;
+ }
+
+ /* If device open already then either re-use it or close it */
+ if (this->client) {
+ if ((mode == this->mode) && (rate == this->input_sample_rate)) {
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG,
+ "ao_jack_open: device already open, reusing it\n");
+ return this->output_sample_rate;
}
- this->buf_read = this->buf_write = 0;
- this->sample_rate = rate;
- this->bits_per_sample = bits;
- this->capabilities = AO_CAP_16BITS | AO_CAP_MODE_MONO | \
- AO_CAP_MODE_STEREO | AO_CAP_MIXER_VOL | AO_CAP_MUTE_VOL;
- this->bytes_per_frame = this->num_channels * (bits / 8);
+ ao_jack_close (this_gen);
+ }
+
+
+ this->mode = mode;
+ this->input_sample_rate = rate;
+ this->bits_per_sample = bits;
+ this->bytes_in_buffer = 0;
+ this->read_pos = this->write_pos = 0;
+ this->paused = 0;
+ this->underrun = 0;
+
+ /*
+ * set number of channels / a52 passthrough
+ */
+ switch (mode) {
+ case AO_CAP_MODE_MONO:
+ this->num_channels = 1;
+ break;
+ case AO_CAP_MODE_STEREO:
+ this->num_channels = 2;
+ break;
+ case AO_CAP_MODE_4CHANNEL:
+ this->num_channels = 4;
+ break;
+ case AO_CAP_MODE_4_1CHANNEL:
+ case AO_CAP_MODE_5CHANNEL:
+ case AO_CAP_MODE_5_1CHANNEL:
+ this->num_channels = 6;
+ break;
+ case AO_CAP_MODE_A52:
+ case AO_CAP_MODE_AC5:
+ /* FIXME: Is this correct...? */
+ this->num_channels = 2;
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG,
+ "ao_jack_open: AO_CAP_MODE_A52\n");
+ break;
+ default:
+ xprintf (this->xine, XINE_VERBOSITY_LOG,
+ "ao_jack_open: JACK Driver does not support the requested mode: 0x%X\n",
+ mode);
+ return 0;
+ }
+
+ xprintf (this->xine, XINE_VERBOSITY_LOG,
+ "ao_jack_open: %d channels output\n", this->num_channels);
+ this->bytes_per_frame = (this->bits_per_sample * this->num_channels) / 8;
+
+ /*
+ * open audio device
+ */
+ if (!jack_open_device (this_gen, jack_device, &(this->output_sample_rate),
+ this->num_channels))
+ return 0;
- fprintf(stderr, "ao_jack_open: bits=%d rate=%d, mode=%d OK\n", bits, rate, mode);
+ if (this->input_sample_rate != this->output_sample_rate) {
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG,
+ "ao_jack_open: audio rate : %d requested, %d provided by device\n",
+ this->input_sample_rate, this->output_sample_rate);
+ }
- return rate;
+ return this->output_sample_rate;
}
-static int ao_jack_num_channels(ao_driver_t *this_gen)
+static int ao_jack_num_channels (ao_driver_t *this_gen)
{
- jack_driver_t *this = (jack_driver_t *) this_gen;
- return this->num_channels;
+ jack_driver_t *this = (jack_driver_t *) this_gen;
+ return this->num_channels;
}
-static int ao_jack_bytes_per_frame(ao_driver_t *this_gen)
+static int ao_jack_bytes_per_frame (ao_driver_t *this_gen)
{
- jack_driver_t *this = (jack_driver_t *) this_gen;
- return this->bytes_per_frame;
+ jack_driver_t *this = (jack_driver_t *) this_gen;
+ return this->bytes_per_frame;
}
static int ao_jack_get_gap_tolerance (ao_driver_t *this_gen)
{
- return GAP_TOLERANCE;
+ return GAP_TOLERANCE;
}
-static int last_write_space = 0;
-
-static int ao_jack_write(ao_driver_t *this_gen, int16_t *data,
- uint32_t num_frames)
+/*
+ * Return the number of outstanding frames in all output buffers
+ * need to account for ring buffer plus Jack, plus soundcard
+ */
+static int ao_jack_delay (ao_driver_t *this_gen)
{
- jack_driver_t *this = (jack_driver_t *) this_gen;
- uint32_t frame, channel;
-
- uint32_t local_buf_read = this->buf_read;
- uint32_t local_buf_write = this->buf_write;
- uint32_t space = (local_buf_read + BUFSIZE - local_buf_write - 1) % BUFSIZE;
- uint32_t first_frame = 0;
-
- int c = 0;
- while (space < num_frames) {
- if (++c == 10) return 0;
- usleep(10000);
- local_buf_read = this->buf_read;
- space = (local_buf_read + BUFSIZE - local_buf_write - 1) % BUFSIZE;
- }
-
-// if (space < num_frames) return 0;
-
-// printf("ao_jack_write: %u frames on %u channels, space is %u\n", num_frames, this->num_channels, space);
- last_write_space = space;
-
- for (frame = first_frame; frame < num_frames; ++frame) {
- for (channel = 0; channel < this->num_channels; ++channel) {
- float *buf = (channel ? this->buf_2 : this->buf_1);
- int16_t sample = data[frame * this->num_channels + channel];
- buf[local_buf_write] = ((float)sample) / 32767.0f;
-// printf("%6f ", buf[local_buf_write]);
-// if (++c == 8) { printf("\n"); c = 0; }
- }
- if (++local_buf_write == BUFSIZE) local_buf_write = 0;
- }
-
- this->buf_write = local_buf_write;
+ jack_driver_t *this = (jack_driver_t *) this_gen;
+ int frames_played = jack_frames_since_cycle_start (this->client);
-// printf("ao_jack_write: buf_read %u, buf_write %u\n", this->buf_read, this->buf_write);
+ int delay = 0;
+ /* Ring Buffer always stores floats */
+ /* TODO: Unsure if the delay should be fragment_size*2 or *3? */
+ delay = buf_used (this) / (sizeof (float) * this->num_channels) +
+ this->fragment_size * 3 - frames_played;
- return 1;
+ return delay;
}
-static int ao_jack_delay (ao_driver_t *this_gen)
+ /* Write audio samples
+ * num_frames is the number of audio frames present
+ * audio frames are equivalent one sample on each channel.
+ * I.E. Stereo 16 bits audio frames are 4 bytes.
+ * MUST SIMULATE BLOCKING WRITES
+ */
+static int ao_jack_write (ao_driver_t *this_gen, int16_t *frame_buffer,
+ uint32_t num_frames)
{
- jack_driver_t *this = (jack_driver_t *) this_gen;
+ jack_driver_t *this = (jack_driver_t *) this_gen;
+ int written = 0;
+ int num_bytes = num_frames * this->bytes_per_frame;
+
+ /* First try and write all the bytes in one go */
+ this->underrun = 0;
+ /* TODO: In the future Xine should pass only floats to us, so no conversion needed */
+ if (this->bits_per_sample == 16)
+ written = write_buffer_16 (this, (char *) frame_buffer, num_bytes);
+ else if (this->bits_per_sample == 32)
+ written = write_buffer_32 (this, (char *) frame_buffer, num_bytes);
+
+ /* If this fails then need to spin and keep trying until everything written */
+ int spin_count = 0;
+ while ((written < num_bytes) && (spin_count < 40)) {
+ num_bytes -= written;
+ frame_buffer += written / 2;
+
+ /* Sleep to save CPU */
+ int until_callback =
+ this->fragment_size - jack_frames_since_cycle_start (this->client);
+ if ((until_callback < 0) || (until_callback > this->fragment_size)) {
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG,
+ "ao_jack_write: Invalid until_callback %d\n", until_callback);
+ until_callback = this->fragment_size;
+ }
+ xine_usec_sleep (((until_callback +
+ 100) * 1000.0 * 1000.0) / this->output_sample_rate);
- uint32_t local_buf_read = this->buf_read;
- uint32_t local_buf_write = this->buf_write;
+ if (this->bits_per_sample == 16)
+ written = write_buffer_16 (this, (char *) frame_buffer, num_bytes);
+ else if (this->bits_per_sample == 32)
+ written = write_buffer_32 (this, (char *) frame_buffer, num_bytes);
- int delay = 0;
+ if (written == 0)
+ spin_count++;
+ else
+ spin_count = 0;
- if (local_buf_write > local_buf_read) {
- delay = local_buf_write - local_buf_read;
- } else {
- delay = ((local_buf_write + BUFSIZE - local_buf_read) % BUFSIZE);
- }
+ if (written == 0)
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG,
+ "ao_jack_write: unusual, couldn't write anything\n");
+ };
- return delay;// - jack_get_buffer_size(this->client);
-}
+ if (spin_count)
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG,
+ "Nonzero spin_count...%d\n", spin_count);
-static void ao_jack_close(ao_driver_t *this_gen)
-{
- // nothing
+ return spin_count ? 0 : 1; /* return 1 on success, 0 if we got stuck for some reason */
}
-static uint32_t ao_jack_get_capabilities (ao_driver_t *this_gen) {
- jack_driver_t *this = (jack_driver_t *) this_gen;
- return this->capabilities;
-}
-
-static void ao_jack_exit(ao_driver_t *this_gen)
+static uint32_t ao_jack_get_capabilities (ao_driver_t *this_gen)
{
- jack_driver_t *this = (jack_driver_t *) this_gen;
- jack_client_t *client = this->client;
- ao_jack_close(this_gen);
- this->client = 0;
- if (client) jack_client_close(client);
- free (this);
+ jack_driver_t *this = (jack_driver_t *) this_gen;
+ return this->capabilities;
}
-static int ao_jack_get_property (ao_driver_t *this_gen, int property) {
- jack_driver_t *this = (jack_driver_t *) this_gen;
-
- switch(property) {
- case AO_PROP_PCM_VOL:
- case AO_PROP_MIXER_VOL:
-// printf("ao_jack_get_property(AO_PROP_MIXER_VOL): %u\n", this->volume);
- return this->volume;
- break;
- case AO_PROP_MUTE_VOL:
-// printf("ao_jack_get_property(AO_PROP_MUTE_VOL): %u\n", this->mute);
- return this->mute;
- break;
- }
+static void ao_jack_exit (ao_driver_t *this_gen)
+{
+ jack_driver_t *this = (jack_driver_t *) this_gen;
- return 0;
+ ao_jack_close (this_gen);
+ if (this->buffer)
+ free (this->buffer);
+ free (this);
}
-static int ao_jack_set_property (ao_driver_t *this_gen, int property, int value) {
- jack_driver_t *this = (jack_driver_t *) this_gen;
-
- switch(property) {
- case AO_PROP_PCM_VOL:
- case AO_PROP_MIXER_VOL:
-// printf("ao_jack_set_property(AO_PROP_MIXER_VOL): %u\n", value);
- this->volume = value;
- break;
- case AO_PROP_MUTE_VOL:
-// printf("ao_jack_get_property(AO_PROP_MUTE_VOL): %u\n", value);
- this->mute = value;
- break;
- }
+static int ao_jack_get_property (ao_driver_t *this_gen, int property)
+{
+ jack_driver_t *this = (jack_driver_t *) this_gen;
+
+ switch (property) {
+ case AO_PROP_PCM_VOL:
+ case AO_PROP_MIXER_VOL:
+ return this->mixer.volume;
+ break;
+ case AO_PROP_MUTE_VOL:
+ return this->mixer.mute;
+ break;
+ }
+
+ return 0;
+}
- return ~value;
+static int ao_jack_set_property (ao_driver_t *this_gen, int property, int value)
+{
+ jack_driver_t *this = (jack_driver_t *) this_gen;
+
+ switch (property) {
+ case AO_PROP_PCM_VOL:
+ case AO_PROP_MIXER_VOL:
+ this->mixer.volume = value;
+ return value;
+ break;
+ case AO_PROP_MUTE_VOL:
+ this->mixer.mute = value;
+ return value;
+ break;
+ }
+
+ return -1;
}
-static int ao_jack_ctrl(ao_driver_t *this_gen, int cmd, ...) {
- jack_driver_t *this = (jack_driver_t *) this_gen;
+static int ao_jack_ctrl (ao_driver_t *this_gen, int cmd, ...)
+{
+ jack_driver_t *this = (jack_driver_t *) this_gen;
- switch (cmd) {
+ switch (cmd) {
- case AO_CTRL_PLAY_PAUSE:
- break;
+ case AO_CTRL_PLAY_PAUSE:
+ this->paused = 1;
+ break;
- case AO_CTRL_PLAY_RESUME:
- break;
+ case AO_CTRL_PLAY_RESUME:
+ this->paused = 0;
+ break;
- case AO_CTRL_FLUSH_BUFFERS:
-// fprintf(stderr, "ao_jack_ctrl(AO_CTRL_FLUSH_BUFFERS)\n");
- this->buf_write = this->buf_read = 0;
- break;
- }
+ case AO_CTRL_FLUSH_BUFFERS:
+ jack_reset (this);
+ break;
+ }
- return 0;
+ return 0;
}
+static void jack_speaker_arrangement_cb (void *user_data,
+ xine_cfg_entry_t *entry);
+
static ao_driver_t *open_jack_plugin (audio_driver_class_t *class_gen,
const void *data)
{
- jack_class_t *class = (jack_class_t *) class_gen;
- jack_driver_t *this;
- jack_client_t *client;
- uint32_t rate;
- const char **port_names;
- int i;
-
- if ((client = jack_client_new("xine")) == 0) {
-
- char name[20];
- sprintf(name, "xine (%d)", (int)getpid());
-
- if ((client = jack_client_new(name)) == 0) {
- fprintf(stderr, "\nopen_jack_plugin: Error: Failed to connect to JACK server\n");
- fprintf(stderr, "open_jack_plugin: (did you start 'jackd' server?)\n");
- return 0;
- }
- }
-
- this = (jack_driver_t *) xine_xmalloc (sizeof (jack_driver_t));
-
- this->client = client;
-
- jack_set_process_callback(client, jack_process, this);
- jack_on_shutdown(client, jack_shutdown, this);
-
- rate = jack_get_sample_rate(client);
- fprintf(stderr, "open_jack_plugin: JACK sample rate is %u\n", rate);
-
- // We support up to 2-channel output
-
- for (i = 0; i < 2; ++i) {
- jack_port_t *port = jack_port_register
- (client, (i ? "out_r" : "out_l"),
- JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
- if (!port) {
- fprintf(stderr, "ao_jack_open: failed to register port %u\n", i);
- }
- if (i) this->port_2 = port;
- else this->port_1 = port;
- }
-
- this->buf_read = this->buf_write = 0;
- this->volume = 100;
- this->mute = 0;
-
- if (jack_activate(client)) {
- fprintf(stderr, "ao_jack_open: failed to activate JACK client\n");
- return 0;
- }
-
- if ((port_names = jack_get_ports(client, NULL, NULL,
- JackPortIsPhysical | JackPortIsInput)) != NULL) {
- if (port_names[0]) {
- jack_connect(client, jack_port_name(this->port_1), port_names[0]);
- }
- if (port_names[1] && this->port_2) {
- jack_connect(client, jack_port_name(this->port_2), port_names[1]);
- }
- free(port_names);
- }
+ jack_class_t *class = (jack_class_t *) class_gen;
+ config_values_t *config = class->config;
+ jack_driver_t *this;
+
+ jack_client_t *client;
+ uint32_t rate;
+ char *jack_device;
+ const char **matching_ports = NULL;
+ const char **port_names;
+
+ /* for usability reasons, keep this in sync with audio_oss_out.c */
+ static char *speaker_arrangement[] = {
+ "Mono 1.0", "Stereo 2.0", "Headphones 2.0", "Stereo 2.1",
+ "Surround 3.0", "Surround 4.0", "Surround 4.1", "Surround 5.0",
+ "Surround 5.1", "Surround 6.0",
+ "Surround 6.1", "Surround 7.1", "Pass Through", NULL
+ };
+#define MONO 0
+#define STEREO 1
+#define HEADPHONES 2
+#define SURROUND21 3
+#define SURROUND3 4
+#define SURROUND4 5
+#define SURROUND41 6
+#define SURROUND5 7
+#define SURROUND51 8
+#define SURROUND6 9
+#define SURROUND61 10
+#define SURROUND71 11
+#define A52_PASSTHRU 12
+ int speakers;
+
+ /* Try to create a client called "xine[-NN]" */
+ if ((client = jack_client_open ("xine", JackNullOption, NULL)) == 0) {
+ xprintf (class->xine, XINE_VERBOSITY_LOG,
+ "\nopen_jack_plugin: Error: Failed to connect to JACK server\n");
+ return 0;
+ }
+
+ this = calloc(1, sizeof (jack_driver_t));
+
+ rate = jack_get_sample_rate (client);
+ xprintf (class->xine, XINE_VERBOSITY_DEBUG,
+ "open_jack_plugin: JACK sample rate is %u\n", rate);
+
+ /* devname_val is offset used to select auto, /dev/dsp, or /dev/sound/dsp */
+ jack_device = config->register_string (config,
+ "audio.device.jack_device_name",
+ "",
+ _("JACK audio device name"),
+ _("Specifies the jack audio device name, "
+ "leave blank for the default physical output port."),
+ 10, NULL, NULL);
+
+ this->capabilities = 0;
+
+
+ /* for usability reasons, keep this in sync with audio_alsa_out.c */
+ speakers =
+ config->register_enum (config, "audio.output.speaker_arrangement",
+ STEREO, speaker_arrangement,
+ _("speaker arrangement"),
+ _("Select how your speakers are arranged, "
+ "this determines which speakers xine uses for sound output. "
+ "The individual values are:\n\n"
+ "Mono 1.0: You have only one speaker.\n"
+ "Stereo 2.0: You have two speakers for left and right channel.\n"
+ "Headphones 2.0: You use headphones.\n"
+ "Stereo 2.1: You have two speakers for left and right channel, and one "
+ "subwoofer for the low frequencies.\n"
+ "Surround 3.0: You have three speakers for left, right and rear channel.\n"
+ "Surround 4.0: You have four speakers for front left and right and rear "
+ "left and right channels.\n"
+ "Surround 4.1: You have four speakers for front left and right and rear "
+ "left and right channels, and one subwoofer for the low frequencies.\n"
+ "Surround 5.0: You have five speakers for front left, center and right and "
+ "rear left and right channels.\n"
+ "Surround 5.1: You have five speakers for front left, center and right and "
+ "rear left and right channels, and one subwoofer for the low frequencies.\n"
+ "Surround 6.0: You have six speakers for front left, center and right and "
+ "rear left, center and right channels.\n"
+ "Surround 6.1: You have six speakers for front left, center and right and "
+ "rear left, center and right channels, and one subwoofer for the low frequencies.\n"
+ "Surround 7.1: You have seven speakers for front left, center and right, "
+ "left and right and rear left and right channels, and one subwoofer for the "
+ "low frequencies.\n"
+ "Pass Through: Your sound system will receive undecoded digital sound from xine. "
+ "You need to connect a digital surround decoder capable of decoding the "
+ "formats you want to play to your sound card's digital output."),
+ 0, jack_speaker_arrangement_cb, this);
+
+ int port_flags = JackPortIsInput;
+ int num_ports;
+ /* list matching ports */
+ if (!jack_device)
+ port_flags |= JackPortIsPhysical;
+ /* Find all the ports matching either the desired device regexp or physical output ports */
+ matching_ports = jack_get_ports (client, jack_device, NULL, port_flags);
+ /* Count 'em */
+ for (num_ports = 0; matching_ports && matching_ports[num_ports];
+ num_ports++)
+ /**/;
+ if (!num_ports) {
+ xprintf (this->xine, XINE_VERBOSITY_LOG,
+ "open_jack_plugin: no physical ports available\n");
+ goto err_out;
+ }
+
+
+/* TODO: We deliberately don't offer mono, let Xine upsample instead? */
+/* if (num_ports >= 1) { */
+/* this->capabilities |= AO_CAP_MODE_MONO; */
+/* xprintf(class->xine, XINE_VERBOSITY_DEBUG, "mono "); */
+/* } */
+
+ if (num_ports >= 2) {
+ this->capabilities |= AO_CAP_MODE_STEREO;
+ xprintf (class->xine, XINE_VERBOSITY_DEBUG, "stereo ");
+ }
+
+ if (num_ports >= 4) {
+ if (speakers == SURROUND4) {
+ this->capabilities |= AO_CAP_MODE_4CHANNEL;
+ xprintf (class->xine, XINE_VERBOSITY_DEBUG, "4-channel ");
+ } else
+ xprintf (class->xine, XINE_VERBOSITY_DEBUG,
+ "(4-channel not enabled in xine config) ");
+ }
+
+ if (num_ports >= 5) {
+ if (speakers == SURROUND5) {
+ this->capabilities |= AO_CAP_MODE_5CHANNEL;
+ xprintf (class->xine, XINE_VERBOSITY_DEBUG, "5-channel ");
+ } else
+ xprintf (class->xine, XINE_VERBOSITY_DEBUG,
+ "(5-channel not enabled in xine config) ");
+ }
+
+ if (num_ports >= 6) {
+ if (speakers == SURROUND51) {
+ this->capabilities |= AO_CAP_MODE_5_1CHANNEL;
+ xprintf (class->xine, XINE_VERBOSITY_DEBUG, "5.1-channel ");
+ } else
+ xprintf (class->xine, XINE_VERBOSITY_DEBUG,
+ "(5.1-channel not enabled in xine config) ");
+ }
+
+ this->buffer = (unsigned char *) malloc (BUFFSIZE);
+ jack_reset (this);
+
+ this->capabilities |= AO_CAP_MIXER_VOL;
+ this->capabilities |= AO_CAP_MUTE_VOL;
+ /* TODO: Currently not respected by Xine, perhaps v1.2? */
+ this->capabilities |= AO_CAP_FLOAT32;
+
+
+ this->mixer.mute = 0;
+ this->mixer.volume = 100;
+
+ this->output_sample_rate = jack_get_sample_rate (client);
+ this->fragment_size = jack_get_buffer_size (client);
+
+ /* Close our JACK client */
+ jack_client_close (client);
+
+ this->xine = class->xine;
+
+ this->ao_driver.get_capabilities = ao_jack_get_capabilities;
+ this->ao_driver.get_property = ao_jack_get_property;
+ this->ao_driver.set_property = ao_jack_set_property;
+ this->ao_driver.open = ao_jack_open;
+ this->ao_driver.num_channels = ao_jack_num_channels;
+ this->ao_driver.bytes_per_frame = ao_jack_bytes_per_frame;
+ this->ao_driver.delay = ao_jack_delay;
+ this->ao_driver.write = ao_jack_write;
+ this->ao_driver.close = ao_jack_close;
+ this->ao_driver.exit = ao_jack_exit;
+ this->ao_driver.get_gap_tolerance = ao_jack_get_gap_tolerance;
+ this->ao_driver.control = ao_jack_ctrl;
+
+ return &this->ao_driver;
+
+err_out:
+ free (matching_ports);
+ if (client)
+ jack_client_close (client);
+ return 0;
+}
- this->sample_rate = rate;
-
- this->xine = class->xine;
- this->capabilities = AO_CAP_FLOAT32 | AO_CAP_MODE_MONO |
- AO_CAP_MODE_STEREO | AO_CAP_MIXER_VOL | AO_CAP_MUTE_VOL;
-
- this->ao_driver.get_capabilities = ao_jack_get_capabilities;
- this->ao_driver.get_property = ao_jack_get_property;
- this->ao_driver.set_property = ao_jack_set_property;
- this->ao_driver.open = ao_jack_open;
- this->ao_driver.num_channels = ao_jack_num_channels;
- this->ao_driver.bytes_per_frame = ao_jack_bytes_per_frame;
- this->ao_driver.delay = ao_jack_delay;
- this->ao_driver.write = ao_jack_write;
- this->ao_driver.close = ao_jack_close;
- this->ao_driver.exit = ao_jack_exit;
- this->ao_driver.get_gap_tolerance = ao_jack_get_gap_tolerance;
- this->ao_driver.control = ao_jack_ctrl;
-
- fprintf(stderr, "jack open_jack_plugin returning %p\n", (void *)(&this->ao_driver));
- return &this->ao_driver;
+static void jack_speaker_arrangement_cb (void *user_data,
+ xine_cfg_entry_t *entry)
+{
+ jack_driver_t *this = (jack_driver_t *) user_data;
+ int32_t value = entry->num_value;
+ if (value == SURROUND4) {
+ this->capabilities |= AO_CAP_MODE_4CHANNEL;
+ } else {
+ this->capabilities &= ~AO_CAP_MODE_4CHANNEL;
+ }
+ if (value == SURROUND41) {
+ this->capabilities |= AO_CAP_MODE_4_1CHANNEL;
+ } else {
+ this->capabilities &= ~AO_CAP_MODE_4_1CHANNEL;
+ }
+ if (value == SURROUND5) {
+ this->capabilities |= AO_CAP_MODE_5CHANNEL;
+ } else {
+ this->capabilities &= ~AO_CAP_MODE_5CHANNEL;
+ }
+ if (value >= SURROUND51) {
+ this->capabilities |= AO_CAP_MODE_5_1CHANNEL;
+ } else {
+ this->capabilities &= ~AO_CAP_MODE_5_1CHANNEL;
+ }
}
/*
* class functions
*/
-static char* get_identifier (audio_driver_class_t *this_gen) {
- return "jack";
+static char *get_identifier (audio_driver_class_t *this_gen)
+{
+ return "jack";
}
-static char* get_description (audio_driver_class_t *this_gen) {
- return _("xine output plugin for JACK Audio Connection Kit");
+static char *get_description (audio_driver_class_t *this_gen)
+{
+ return _("xine output plugin for JACK Audio Connection Kit");
}
-static void dispose_class (audio_driver_class_t *this_gen) {
-
- jack_class_t *this = (jack_class_t *) this_gen;
- free (this);
+static void dispose_class (audio_driver_class_t *this_gen)
+{
+ jack_class_t *this = (jack_class_t *) this_gen;
+ free (this);
}
-static void *init_class (xine_t *xine, void *data) {
-
- jack_class_t *this;
-
- this = (jack_class_t *) xine_xmalloc (sizeof (jack_class_t));
+static void *init_class (xine_t *xine, void *data)
+{
+ jack_class_t *this;
- this->driver_class.open_plugin = open_jack_plugin;
- this->driver_class.get_identifier = get_identifier;
- this->driver_class.get_description = get_description;
- this->driver_class.dispose = dispose_class;
+ this = calloc(1, sizeof (jack_class_t));
- this->config = xine->config;
- this->xine = xine;
+ this->driver_class.open_plugin = open_jack_plugin;
+ this->driver_class.get_identifier = get_identifier;
+ this->driver_class.get_description = get_description;
+ this->driver_class.dispose = dispose_class;
- fprintf(stderr, "jack init_class returning %p\n", (void *)this);
+ this->config = xine->config;
+ this->xine = xine;
- return this;
+ return this;
}
-static ao_info_t ao_info_jack = {
- 6
-};
+static ao_info_t ao_info_jack = { 6 };
/*
* exported plugin catalog entry
*/
const plugin_info_t xine_plugin_info[] EXPORTED = {
- /* type, API, "name", version, special_info, init_function */
- { PLUGIN_AUDIO_OUT, AO_OUT_JACK_IFACE_VERSION, "jack", XINE_VERSION_CODE /* XINE_VERSION_CODE */, &ao_info_jack, init_class },
- { PLUGIN_NONE, 0, "", 0, NULL, NULL }
+ /* type, API, "name", version, special_info, init_function */
+ { PLUGIN_AUDIO_OUT, AO_OUT_JACK_IFACE_VERSION, "jack", XINE_VERSION_CODE,
+ &ao_info_jack, init_class },
+ { PLUGIN_NONE, 0, "", 0, NULL, NULL }
};
-
diff --git a/src/audio_out/audio_none_out.c b/src/audio_out/audio_none_out.c
index a815d645a..c3d351035 100644
--- a/src/audio_out/audio_none_out.c
+++ b/src/audio_out/audio_none_out.c
@@ -1,18 +1,18 @@
-/*
+/*
* Copyright (C) 2000-2003 the xine project
- *
+ *
* This file is part of xine, a free video player.
- *
+ *
* xine 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.
- *
+ *
* xine 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
@@ -40,7 +40,7 @@
#define AUDIO_NUM_FRAGMENTS 15
#define AUDIO_FRAGMENT_SIZE 8192
-#define GAP_TOLERANCE AO_MAX_GAP
+#define GAP_TOLERANCE AO_MAX_GAP
typedef struct none_driver_s {
@@ -74,7 +74,7 @@ static int ao_none_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int
{
none_driver_t *this = (none_driver_t *) this_gen;
- xprintf (this->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG,
"audio_none_out: ao_open bits=%d rate=%d, mode=%d\n", bits, rate, mode);
this->mode = mode;
@@ -115,13 +115,13 @@ static int ao_none_write(ao_driver_t *this_gen, int16_t *data,
uint32_t num_frames)
{
none_driver_t *this = (none_driver_t *) this_gen;
-
+
/* take some time to pretend we are doing something.
* avoids burning cpu.
*/
if( (1000 * num_frames / this->sample_rate) > 10 )
xine_usec_sleep ((1000 * num_frames / this->sample_rate)*1000/2);
-
+
return 1;
}
@@ -143,7 +143,7 @@ static uint32_t ao_none_get_capabilities (ao_driver_t *this_gen) {
static void ao_none_exit(ao_driver_t *this_gen)
{
none_driver_t *this = (none_driver_t *) this_gen;
-
+
ao_none_close(this_gen);
free (this);
@@ -177,7 +177,7 @@ static int ao_none_ctrl(ao_driver_t *this_gen, int cmd, ...) {
return 0;
}
-static ao_driver_t *open_plugin (audio_driver_class_t *class_gen,
+static ao_driver_t *open_plugin (audio_driver_class_t *class_gen,
const void *data) {
none_class_t *class = (none_class_t *) class_gen;
@@ -186,7 +186,7 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen,
lprintf ("open_plugin called\n");
- this = (none_driver_t *) xine_xmalloc (sizeof (none_driver_t));
+ this = calloc(1, sizeof (none_driver_t));
if (!this)
return NULL;
@@ -236,7 +236,7 @@ static void *init_class (xine_t *xine, void *data) {
lprintf ("init class\n");
- this = (none_class_t *) xine_xmalloc (sizeof (none_class_t));
+ this = calloc(1, sizeof (none_class_t));
if (!this)
return NULL;
@@ -260,7 +260,7 @@ static const ao_info_t ao_info_none = {
*/
const plugin_info_t xine_plugin_info[] EXPORTED = {
- /* type, API, "name", version, special_info, init_function */
+ /* type, API, "name", version, special_info, init_function */
{ PLUGIN_AUDIO_OUT, AO_OUT_NONE_IFACE_VERSION, "none", XINE_VERSION_CODE, &ao_info_none, init_class },
{ PLUGIN_NONE, 0, "", 0, NULL, NULL }
};
diff --git a/src/audio_out/audio_oss_out.c b/src/audio_out/audio_oss_out.c
index a6e0fe494..bd16a6dd3 100644
--- a/src/audio_out/audio_oss_out.c
+++ b/src/audio_out/audio_oss_out.c
@@ -1,25 +1,25 @@
-/*
- * Copyright (C) 2000-2003 the xine project
- *
+/*
+ * Copyright (C) 2000-2008 the xine project
+ *
* This file is part of xine, a free video player.
- *
+ *
* xine 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.
- *
+ *
* xine 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* 20-8-2001 First implementation of Audio sync and Audio driver separation.
* Copyright (C) 2001 James Courtier-Dutton James@superbug.demon.co.uk
- *
+ *
* General Programming Guidelines: -
* New concept of an "audio_frame".
* An audio_frame consists of all the samples required to fill every audio channel
@@ -90,7 +90,7 @@
#endif
#ifndef AFMT_AC3
-# define AFMT_AC3 0x00000400
+# define AFMT_AC3 0x00000400
#endif
#define AO_OUT_OSS_IFACE_VERSION 8
@@ -127,7 +127,7 @@ typedef struct oss_driver_s {
uint32_t bytes_per_frame;
uint32_t bytes_in_buffer; /* number of bytes writen to audio hardware */
uint32_t last_getoptr;
-
+
int audio_started;
int sync_method;
int latency;
@@ -178,7 +178,7 @@ static int ao_oss_open(ao_driver_t *this_gen,
close (this->audio_fd);
}
-
+
this->mode = mode;
this->input_sample_rate = rate;
this->bits_per_sample = bits;
@@ -192,11 +192,11 @@ static int ao_oss_open(ao_driver_t *this_gen,
this->audio_fd=open(this->audio_dev,O_WRONLY|O_NONBLOCK);
if (this->audio_fd < 0) {
- xprintf(this->xine, XINE_VERBOSITY_LOG,
+ xprintf(this->xine, XINE_VERBOSITY_LOG,
_("audio_oss_out: Opening audio device %s: %s\n"), this->audio_dev, strerror(errno));
return 0;
}
-
+
/* We wanted non blocking open but now put it back to normal */
fcntl(this->audio_fd, F_SETFL, fcntl(this->audio_fd, F_GETFL)&~O_NONBLOCK);
@@ -213,8 +213,8 @@ static int ao_oss_open(ao_driver_t *this_gen,
tmp = this->input_sample_rate;
if (ioctl(this->audio_fd,SNDCTL_DSP_SPEED, &tmp) == -1) {
-
- xprintf(this->xine, XINE_VERBOSITY_LOG,
+
+ xprintf(this->xine, XINE_VERBOSITY_LOG,
_("audio_oss_out: warning: sampling rate %d Hz not supported, trying 44100 Hz\n"),
this->input_sample_rate);
@@ -272,7 +272,7 @@ static int ao_oss_open(ao_driver_t *this_gen,
xprintf(this->xine, XINE_VERBOSITY_LOG, "audio_oss_out: %d channels output\n", this->num_channels);
this->bytes_per_frame=(this->bits_per_sample*this->num_channels)/8;
-
+
/*
* set format
*/
@@ -303,7 +303,7 @@ static int ao_oss_open(ao_driver_t *this_gen,
else
xprintf(this->xine, XINE_VERBOSITY_DEBUG, "audio_oss_out: The AFMT_S16_NE ioctl failed.\n");
return 0;
- }
+ }
}
break;
case AO_CAP_MODE_A52:
@@ -317,7 +317,7 @@ static int ao_oss_open(ao_driver_t *this_gen,
ioctl(this->audio_fd, SNDCTL_DSP_CHANNELS, &tmp);
tmp = AFMT_AC3;
if (ioctl(this->audio_fd, SNDCTL_DSP_SETFMT, &tmp) < 0 || tmp != AFMT_AC3) {
- xprintf(this->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->xine, XINE_VERBOSITY_DEBUG,
"audio_oss_out: AC3 SNDCTL_DSP_SETFMT failed. %d. Using alternative.\n",tmp);
tmp = AFMT_S16_LE;
ioctl(this->audio_fd, SNDCTL_DSP_SETFMT, &tmp);
@@ -344,7 +344,7 @@ static int ao_oss_open(ao_driver_t *this_gen,
printf ("audio_oss_out: audio buffer fragment info : %x\n",tmp);
- ioctl(this->audio_fd,SNDCTL_DSP_SETFRAGMENT,&tmp);
+ ioctl(this->audio_fd,SNDCTL_DSP_SETFRAGMENT,&tmp);
*/
return this->output_sample_rate;
@@ -395,9 +395,9 @@ static int ao_oss_delay(ao_driver_t *this_gen) {
* this->output_sample_k_rate / 1000;
frames += (tv.tv_sec - this->start_time.tv_sec)
* this->output_sample_rate;
-
+
frames -= this->latency * this->output_sample_k_rate;
-
+
/* calc delay */
bytes_left = this->bytes_in_buffer - frames * this->bytes_per_frame;
@@ -405,35 +405,37 @@ static int ao_oss_delay(ao_driver_t *this_gen) {
if (bytes_left<=0) /* buffer ran dry */
bytes_left = 0;
break;
+ case OSS_SYNC_GETODELAY:
+#ifdef SNDCTL_DSP_GETODELAY
+ if (ioctl (this->audio_fd, SNDCTL_DSP_GETODELAY, &bytes_left)) {
+ perror ("audio_oss_out: DSP_GETODELAY ioctl():");
+ }
+ if (bytes_left<0)
+ bytes_left = 0;
+
+ lprintf ("%d bytes left\n", bytes_left);
+
+ break;
+#endif
case OSS_SYNC_GETOPTR:
if (ioctl (this->audio_fd, SNDCTL_DSP_GETOPTR, &info)) {
perror ("audio_oss_out: SNDCTL_DSP_GETOPTR failed:");
}
-
+
lprintf ("%d bytes output\n", info.bytes);
if (this->bytes_in_buffer < info.bytes) {
this->bytes_in_buffer -= this->last_getoptr; /* GETOPTR wrapped */
- }
-
+ }
+
bytes_left = this->bytes_in_buffer - info.bytes; /* calc delay */
-
+
if (bytes_left<=0) { /* buffer ran dry */
bytes_left = 0;
this->bytes_in_buffer = info.bytes;
}
this->last_getoptr = info.bytes;
break;
- case OSS_SYNC_GETODELAY:
- if (ioctl (this->audio_fd, SNDCTL_DSP_GETODELAY, &bytes_left)) {
- perror ("audio_oss_out: DSP_GETODELAY ioctl():");
- }
- if (bytes_left<0)
- bytes_left = 0;
-
- lprintf ("%d bytes left\n", bytes_left);
-
- break;
}
return bytes_left / this->bytes_per_frame;
@@ -474,7 +476,7 @@ static int ao_oss_write(ao_driver_t *this_gen,
this->bytes_in_buffer += num_frames * this->bytes_per_frame;
- n = write(this->audio_fd, frame_buffer, num_frames * this->bytes_per_frame);
+ n = write(this->audio_fd, frame_buffer, num_frames * this->bytes_per_frame);
lprintf ("ao_oss_write done\n");
@@ -518,20 +520,20 @@ static int ao_oss_get_property (ao_driver_t *this_gen, int property) {
case AO_PROP_PCM_VOL:
case AO_PROP_MIXER_VOL:
if(!this->mixer.mute) {
-
+
if(this->mixer.fd != -1) {
IOCTL_REQUEST_TYPE cmd = 0;
int v;
-
+
ioctl(this->mixer.fd, SOUND_MIXER_READ_DEVMASK, &audio_devs);
-
+
if(audio_devs & SOUND_MASK_PCM)
cmd = SOUND_MIXER_READ_PCM;
else if(audio_devs & SOUND_MASK_VOLUME)
cmd = SOUND_MIXER_READ_VOLUME;
else
return -1;
-
+
ioctl(this->mixer.fd, cmd, &v);
this->mixer.volume = (((v & 0xFF00) >> 8) + (v & 0x00FF)) / 2;
} else
@@ -557,20 +559,20 @@ static int ao_oss_set_property (ao_driver_t *this_gen, int property, int value)
case AO_PROP_PCM_VOL:
case AO_PROP_MIXER_VOL:
if(!this->mixer.mute) {
-
+
if(this->mixer.fd != -1) {
IOCTL_REQUEST_TYPE cmd = 0;
int v;
-
+
ioctl(this->mixer.fd, SOUND_MIXER_READ_DEVMASK, &audio_devs);
-
+
if(audio_devs & SOUND_MASK_PCM)
cmd = SOUND_MIXER_WRITE_PCM;
else if(audio_devs & SOUND_MASK_VOLUME)
cmd = SOUND_MIXER_WRITE_VOLUME;
else
return -1;
-
+
v = (value << 8) | value;
ioctl(this->mixer.fd, cmd, &v);
this->mixer.volume = value;
@@ -586,26 +588,26 @@ static int ao_oss_set_property (ao_driver_t *this_gen, int property, int value)
this->mixer.mute = (value) ? 1 : 0;
if(this->mixer.mute) {
-
+
if(this->mixer.fd != -1) {
IOCTL_REQUEST_TYPE cmd = 0;
int v = 0;
-
+
ioctl(this->mixer.fd, SOUND_MIXER_READ_DEVMASK, &audio_devs);
-
+
if(audio_devs & SOUND_MASK_PCM)
cmd = SOUND_MIXER_WRITE_PCM;
else if(audio_devs & SOUND_MASK_VOLUME)
cmd = SOUND_MIXER_WRITE_VOLUME;
else
return -1;
-
+
ioctl(this->mixer.fd, cmd, &v);
} else
return -1;
} else
(void) ao_oss_set_property(&this->ao_driver, this->mixer.prop, this->mixer.volume);
-
+
return value;
break;
}
@@ -623,7 +625,7 @@ static int ao_oss_ctrl(ao_driver_t *this_gen, int cmd, ...) {
if (this->sync_method != OSS_SYNC_SOFTSYNC)
ioctl(this->audio_fd, SNDCTL_DSP_RESET, NULL);
-
+
/* close/reopen if RESET causes problems */
if (this->sync_method == OSS_SYNC_GETOPTR) {
ao_oss_close(this_gen);
@@ -639,7 +641,7 @@ static int ao_oss_ctrl(ao_driver_t *this_gen, int cmd, ...) {
lprintf ("AO_CTRL_FLUSH_BUFFERS\n");
if (this->sync_method != OSS_SYNC_SOFTSYNC)
ioctl(this->audio_fd, SNDCTL_DSP_RESET, NULL);
-
+
if (this->sync_method == OSS_SYNC_GETOPTR) {
ao_oss_close(this_gen);
ao_oss_open(this_gen, this->bits_per_sample, this->input_sample_rate, this->mode);
@@ -685,14 +687,14 @@ static int probe_audio_devices(oss_driver_t *this) {
strcpy(this->audio_dev, devname); /* Better, keep this one */
best_rate = rate;
}
-
+
close (audio_fd);
}
}
}
return best_rate; /* Will be zero if we did not find one */
-}
-
+}
+
static void oss_speaker_arrangement_cb (void *user_data,
xine_cfg_entry_t *entry);
@@ -726,8 +728,8 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da
#define A52_PASSTHRU 12
int speakers;
-
- this = (oss_driver_t *) xine_xmalloc (sizeof (oss_driver_t));
+
+ this = calloc(1, sizeof (oss_driver_t));
if (!this)
return NULL;
@@ -760,7 +762,7 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da
xprintf(class->xine, XINE_VERBOSITY_LOG,
_("audio_oss_out: audio.device.oss_device_name = auto, probing devs\n"));
if ( ! probe_audio_devices(this)) { /* Returns zero on fail */
- xprintf(class->xine, XINE_VERBOSITY_LOG,
+ xprintf(class->xine, XINE_VERBOSITY_LOG,
_("audio_oss_out: Auto probe for audio device failed\n"));
free (this);
return NULL;
@@ -782,18 +784,18 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da
audio_fd = open(this->audio_dev, O_WRONLY|O_NONBLOCK);
if (audio_fd < 0) {
- xprintf(class->xine, XINE_VERBOSITY_LOG,
+ xprintf(class->xine, XINE_VERBOSITY_LOG,
_("audio_oss_out: opening audio device %s failed:\n%s\n"), this->audio_dev, strerror(errno));
free (this);
return NULL;
- }
+ }
/*
* set up driver to reasonable values for capabilities tests
*/
- arg = AFMT_S16_NE;
+ arg = AFMT_S16_NE;
status = ioctl(audio_fd, SNDCTL_DSP_SETFMT, &arg);
arg = 44100;
status = ioctl(audio_fd, SNDCTL_DSP_SPEED, &arg);
@@ -803,7 +805,7 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da
*/
this->sync_method = config->register_enum (config, "audio.oss_sync_method", OSS_SYNC_AUTO_DETECT,
- sync_methods,
+ sync_methods,
_("a/v sync method to use by OSS"),
_("xine can use different methods to keep audio and video "
"synchronized. Which setting works best depends on the "
@@ -840,10 +842,13 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da
* check if SNDCTL_DSP_GETODELAY works. if so, using it is preferred.
*/
+#ifdef SNDCTL_DSP_GETODELAY
if (ioctl(audio_fd, SNDCTL_DSP_GETODELAY, &info) != -1) {
xprintf(class->xine, XINE_VERBOSITY_DEBUG, "audio_oss_out: using SNDCTL_DSP_GETODELAY\n");
this->sync_method = OSS_SYNC_GETODELAY;
- } else if (ioctl(audio_fd, SNDCTL_DSP_GETOPTR, &info) != -1) {
+ } else
+#endif
+ if (ioctl(audio_fd, SNDCTL_DSP_GETOPTR, &info) != -1) {
xprintf(class->xine, XINE_VERBOSITY_DEBUG, "audio_oss_out: using SNDCTL_DSP_GETOPTR\n");
this->sync_method = OSS_SYNC_GETOPTR;
} else {
@@ -857,9 +862,9 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da
"audio_oss_out: ...will use system real-time clock for soft-sync instead\n"
"audio_oss_out: ...there may be audio/video synchronization issues\n"));
xine_monotonic_clock(&this->start_time, NULL);
-
+
this->latency = config->register_range (config, "audio.oss_latency", 0,
- -3000, 3000,
+ -3000, 3000,
_("OSS audio output latency (adjust a/v sync)"),
_("If you experience audio being not in sync "
"with the video, you can enter a fixed offset "
@@ -868,34 +873,30 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da
"of a second."),
20, NULL, NULL);
}
-
+
if (this->sync_method == OSS_SYNC_PROBEBUFFER) {
char *buf;
int c;
-
- xprintf(class->xine, XINE_VERBOSITY_LOG,
- _("audio_oss_out: Audio driver realtime sync disabled...\n"
- "audio_oss_out: ...probing output buffer size: "));
+
this->buffer_size = 0;
-
- if( (buf=malloc(1024)) != NULL ) {
- memset(buf,0,1024);
-
+
+ if( (buf=calloc(1, 1024)) != NULL ) {
do {
c = write(audio_fd,buf,1024);
if( c != -1 )
this->buffer_size += c;
} while( c == 1024 );
-
+
free(buf);
}
close(audio_fd);
xprintf(class->xine, XINE_VERBOSITY_LOG,
- _("%d bytes\naudio_oss_out: ...there may be audio/video synchronization issues\n"), this->buffer_size);
+ _("audio_oss_out: Audio driver realtime sync disabled...\n"
+ "audio_oss_out: ...probing output buffer size: %d bytes\naudio_oss_out: ...there may be audio/video synchronization issues\n"), this->buffer_size);
audio_fd=open(this->audio_dev, O_WRONLY|O_NONBLOCK);
- if(audio_fd < 0)
+ if(audio_fd < 0)
{
xprintf(class->xine, XINE_VERBOSITY_LOG,
_("audio_oss_out: opening audio device %s failed:\n%s\n"), this->audio_dev, strerror(errno));
@@ -906,11 +907,11 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da
}
this->capabilities = 0;
-
+
arg = AFMT_U8;
if( ioctl(audio_fd, SNDCTL_DSP_SETFMT, &arg) != -1 && arg == AFMT_U8)
this->capabilities |= AO_CAP_8BITS;
-
+
/* switch back to 16bits, because some soundcards otherwise do not report all their capabilities */
arg = AFMT_S16_NE;
if (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &arg) == -1 || arg != AFMT_S16_NE) {
@@ -954,48 +955,48 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da
0, oss_speaker_arrangement_cb, this);
- xprintf(class->xine, XINE_VERBOSITY_DEBUG, "audio_oss_out: supported modes are ");
- num_channels = 1;
- status = ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &num_channels);
+ char *logmsg = strdup (_("audio_oss_out: supported modes are"));
+ num_channels = 1;
+ status = ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &num_channels);
if ( (status != -1) && (num_channels==1) ) {
this->capabilities |= AO_CAP_MODE_MONO;
- xprintf(class->xine, XINE_VERBOSITY_DEBUG, "mono ");
+ xine_strcat_realloc (&logmsg, _(" mono"));
}
- num_channels = 2;
- status = ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &num_channels);
+ num_channels = 2;
+ status = ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &num_channels);
if ( (status != -1) && (num_channels==2) ) {
this->capabilities |= AO_CAP_MODE_STEREO;
- xprintf(class->xine, XINE_VERBOSITY_DEBUG, "stereo ");
+ xine_strcat_realloc (&logmsg, _(" stereo"));
}
- num_channels = 4;
- status = ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &num_channels);
+ num_channels = 4;
+ status = ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &num_channels);
if ( (status != -1) && (num_channels==4) ) {
if ( speakers == SURROUND4 ) {
this->capabilities |= AO_CAP_MODE_4CHANNEL;
- xprintf(class->xine, XINE_VERBOSITY_DEBUG, "4-channel ");
- }
+ xine_strcat_realloc (&logmsg, _(" 4-channel"));
+ }
else
- xprintf(class->xine, XINE_VERBOSITY_DEBUG, "(4-channel not enabled in xine config) " );
+ xine_strcat_realloc (&logmsg, _(" (4-channel not enabled in xine config)"));
}
- num_channels = 5;
- status = ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &num_channels);
+ num_channels = 5;
+ status = ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &num_channels);
if ( (status != -1) && (num_channels==5) ) {
if ( speakers == SURROUND5 ) {
this->capabilities |= AO_CAP_MODE_5CHANNEL;
- xprintf(class->xine, XINE_VERBOSITY_DEBUG, "5-channel ");
+ xine_strcat_realloc (&logmsg, _(" 5-channel"));
}
else
- xprintf(class->xine, XINE_VERBOSITY_DEBUG, "(5-channel not enabled in xine config) " );
+ xine_strcat_realloc (&logmsg, _(" (5-channel not enabled in xine config)"));
}
- num_channels = 6;
- status = ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &num_channels);
+ num_channels = 6;
+ status = ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &num_channels);
if ( (status != -1) && (num_channels==6) ) {
if ( speakers == SURROUND51 ) {
this->capabilities |= AO_CAP_MODE_5_1CHANNEL;
- xprintf(class->xine, XINE_VERBOSITY_DEBUG, "5.1-channel ");
- }
+ xine_strcat_realloc (&logmsg, _(" 5.1-channel"));
+ }
else
- xprintf(class->xine, XINE_VERBOSITY_DEBUG, "(5.1-channel not enabled in xine config) " );
+ xine_strcat_realloc (&logmsg, _(" (5.1-channel not enabled in xine config)"));
}
ioctl(audio_fd,SNDCTL_DSP_GETFMTS,&caps);
@@ -1005,11 +1006,14 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da
if ( speakers == A52_PASSTHRU ) {
this->capabilities |= AO_CAP_MODE_A52;
this->capabilities |= AO_CAP_MODE_AC5;
- xprintf(class->xine, XINE_VERBOSITY_DEBUG, "a/52-pass-through ");
- }
- else
- xprintf(class->xine, XINE_VERBOSITY_DEBUG, "(a/52-pass-through not enabled in xine config)");
-
+ xine_strcat_realloc (&logmsg, _(" a/52 pass-through"));
+ }
+ else
+ xine_strcat_realloc (&logmsg, _(" (a/52 pass-through not enabled in xine config)"));
+
+ xprintf(class->xine, XINE_VERBOSITY_DEBUG, "%s\n", logmsg);
+ free (logmsg);
+
/*
* mixer initialisation.
*/
@@ -1018,7 +1022,7 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da
int mixer_num;
int audio_devs;
char *parse;
-
+
mixer_num = config->register_num(config, "audio.device.oss_mixer_number", -1,
_("OSS audio mixer number, -1 for none"),
_("The full mixer device name is created by taking the "
@@ -1029,33 +1033,30 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da
"The range of this value is -1 or 0-15. This setting is "
"ignored, when the OSS audio device name is set to \"auto\"."),
10, NULL, NULL);
-
+
/* get the mixer device name from the audio device name by replacing "dsp" with "mixer" */
strcpy(mixer_name, this->audio_dev);
if ((parse = strstr(mixer_name, "dsp"))) {
parse[0] = '\0';
parse += 3;
- this->mixer.name = (char *)malloc(strlen(mixer_name) + sizeof("mixer") + 2);
if (devname_val == 0)
- sprintf(this->mixer.name, "%smixer%s", mixer_name, parse);
+ asprintf(&(this->mixer.name), "%smixer%s", mixer_name, parse);
else {
if (mixer_num == -1)
- sprintf(this->mixer.name, "%smixer", mixer_name);
+ asprintf(&(this->mixer.name), "%smixer", mixer_name);
else
- sprintf(this->mixer.name, "%smixer%d", mixer_name, mixer_num);
+ asprintf(&(this->mixer.name), "%smixer%d", mixer_name, mixer_num);
}
} else {
- this->mixer.name = (char *)malloc(1);
- this->mixer.name[0] = '\0';
+ _x_abort();
}
- _x_assert(this->mixer.name[0] != '\0');
-
+
this->mixer.fd = open(this->mixer.name, O_RDONLY);
if(this->mixer.fd != -1) {
ioctl(this->mixer.fd, SOUND_MIXER_READ_DEVMASK, &audio_devs);
-
+
if(audio_devs & SOUND_MASK_PCM) {
this->capabilities |= AO_CAP_PCM_VOL;
this->mixer.prop = AO_PROP_PCM_VOL;
@@ -1064,9 +1065,9 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da
this->capabilities |= AO_CAP_MIXER_VOL;
this->mixer.prop = AO_PROP_MIXER_VOL;
}
-
+
/*
- * This is obsolete in Linux kernel OSS
+ * This is obsolete in Linux kernel OSS
* implementation, so this will certainly doesn't work.
* So we just simulate the mute stuff
*/
@@ -1075,11 +1076,11 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da
this->capabilities |= AO_CAP_MUTE_VOL;
*/
this->capabilities |= AO_CAP_MUTE_VOL;
-
- } else
+
+ } else
xprintf (class->xine, XINE_VERBOSITY_LOG,
_("audio_oss_out: open() mixer %s failed: %s\n"), this->mixer.name, strerror(errno));
-
+
this->mixer.mute = 0;
this->mixer.volume = ao_oss_get_property (&this->ao_driver, this->mixer.prop);
@@ -1165,7 +1166,7 @@ static void *init_class (xine_t *xine, void *data) {
oss_class_t *this;
- this = (oss_class_t *) xine_xmalloc (sizeof (oss_class_t));
+ this = calloc(1, sizeof (oss_class_t));
if (!this)
return NULL;
@@ -1189,7 +1190,7 @@ static const ao_info_t ao_info_oss = {
*/
const plugin_info_t xine_plugin_info[] EXPORTED = {
- /* type, API, "name", version, special_info, init_function */
+ /* type, API, "name", version, special_info, init_function */
{ PLUGIN_AUDIO_OUT, AO_OUT_OSS_IFACE_VERSION, "oss", XINE_VERSION_CODE, &ao_info_oss, init_class },
{ PLUGIN_NONE, 0, "", 0, NULL, NULL }
};
diff --git a/src/audio_out/audio_pulse_out.c b/src/audio_out/audio_pulse_out.c
index 26d121bf6..d4d19ce1b 100644
--- a/src/audio_out/audio_pulse_out.c
+++ b/src/audio_out/audio_pulse_out.c
@@ -1,28 +1,28 @@
-/*
- * Copyright (C) 2000-2007 the xine project
- *
+/* -*- Mode: C; c-basic-offset: 2; indent-tabs-mode: nil -*- */
+
+/*
+ * Copyright (C) 2000-2008 the xine project
+ *
* This file is part of xine, a free video player.
- *
+ *
* xine 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.
- *
+ *
* xine 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
- * ao plugin for pulseaudio (rename of polypaudio):
+ * ao plugin for PulseAudio:
* http://0pointer.de/lennart/projects/pulsaudio/
*
- * originally written for polypaudio simple api. Lennart then suggested
- * using the async api for better control (such as volume), therefore, a lot
- * of this code comes from Lennart's patch to mplayer.
+ * Diego Petteno, Lennart Poettering
*/
#ifdef HAVE_CONFIG_H
@@ -48,15 +48,9 @@
#define GAP_TOLERANCE AO_MAX_GAP
-/* CHECKME: should this be conditional on autotools? */
-extern const char *__progname;
-
typedef struct {
audio_driver_class_t driver_class;
xine_t *xine;
-
- struct pa_context *context; /*< Pulseaudio connection context */
- struct pa_threaded_mainloop *mainloop; /*< Main event loop object */
} pulse_class_t;
typedef struct pulse_driver_s {
@@ -67,11 +61,13 @@ typedef struct pulse_driver_s {
char *host; /*< The host to connect to */
char *sink; /*< The sink to connect to */
- struct pa_stream *stream; /*< Pulseaudio playback stream object */
- pthread_mutex_t info_mutex; /**< Mutex for info callback signaling */
+ pa_threaded_mainloop *mainloop; /*< Main event loop object */
+ pa_context *context; /*< Pulseaudio connection context */
+ pa_stream *stream; /*< Pulseaudio playback stream object */
pa_volume_t swvolume;
+ int muted;
pa_cvolume cvolume;
int capabilities;
@@ -82,67 +78,117 @@ typedef struct pulse_driver_s {
uint32_t bits_per_sample;
uint32_t bytes_per_frame;
- uint32_t frames_written;
-
} pulse_driver_t;
/**
- * @brief Callback function called when a stream operation succeed
- * @param stream Stream which operation has succeeded
- * @param success The success value for the operation (ignored)
- * @param this_Gen pulse_driver_t pointer for the PulseAudio output
- * instance.
+ * @brief Callback function called when the state of the context is changed
+ * @param c Context which changed status
+ * @param this_gen pulse_class_t pointer for the PulseAudio output class
*/
-static void __xine_pa_stream_success_callback(pa_stream *const stream, const int success,
- void *const mutex_gen)
+static void __xine_pa_context_state_callback(pa_context *c, void *this_gen)
{
- pthread_mutex_t *const completion_mutex = (pthread_mutex_t*)mutex_gen;
+ pulse_driver_t * this = (pulse_driver_t*) this_gen;
+
+ switch (pa_context_get_state(c)) {
- pthread_mutex_unlock(completion_mutex);
+ case PA_CONTEXT_READY:
+ case PA_CONTEXT_TERMINATED:
+ case PA_CONTEXT_FAILED:
+ pa_threaded_mainloop_signal(this->mainloop, 0);
+ break;
+
+ case PA_CONTEXT_CONNECTING:
+ case PA_CONTEXT_UNCONNECTED:
+ case PA_CONTEXT_AUTHORIZING:
+ case PA_CONTEXT_SETTING_NAME:
+ break;
+ }
}
/**
- * @brief Callback function called when the state of the context is changed
- * @param ctx Context which operation has succeeded
+ * @brief Callback function called when the state of the stream is changed
+ * @param s Stream that changed status
* @param this_gen pulse_driver_t pointer for the PulseAudio output
* instance.
*/
-static void __xine_pa_context_status_callback(pa_context *const ctx, void *const this_gen)
+static void __xine_pa_stream_state_callback(pa_stream *s, void *this_gen)
{
- pulse_driver_t *const this = (pulse_driver_t*)this_gen;
-
- switch (pa_context_get_state(ctx)) {
- case PA_CONTEXT_READY:
- case PA_CONTEXT_TERMINATED:
- case PA_CONTEXT_FAILED:
- pa_threaded_mainloop_signal(this->pa_class->mainloop, 0);
- break;
-
- case PA_CONTEXT_CONNECTING:
- case PA_CONTEXT_UNCONNECTED:
- case PA_CONTEXT_AUTHORIZING:
- case PA_CONTEXT_SETTING_NAME:
- break;
+ pulse_driver_t * this = (pulse_driver_t*) this_gen;
+
+ switch (pa_stream_get_state(s)) {
+
+ case PA_STREAM_READY:
+ case PA_STREAM_TERMINATED:
+ case PA_STREAM_FAILED:
+ pa_threaded_mainloop_signal(this->mainloop, 0);
+ break;
+
+ case PA_STREAM_UNCONNECTED:
+ case PA_STREAM_CREATING:
+ break;
}
}
/**
- * @brief Callback function called when a context operation succeed
+ * @brief Callback function called when PA asks for more audio data.
+ * @param s Stream on which data is requested
+ * @param nbytes the number of bytes PA requested
+ * @param this_gen pulse_driver_t pointer for the PulseAudio output
+ * instance.
+ */
+static void __xine_pa_stream_request_callback(pa_stream *s, size_t nbytes, void *this_gen)
+{
+ pulse_driver_t * this = (pulse_driver_t*) this_gen;
+
+ pa_threaded_mainloop_signal(this->mainloop, 0);
+}
+
+/**
+ * @brief Callback function called when PA notifies about something
+ * @param s Stream on which the notification happened
+ * @param this_gen pulse_driver_t pointer for the PulseAudio output
+ * instance.
+ */
+static void __xine_pa_stream_notify_callback(pa_stream *s, void *this_gen)
+{
+ pulse_driver_t * this = (pulse_driver_t*) this_gen;
+
+ pa_threaded_mainloop_signal(this->mainloop, 0);
+}
+
+/**
+ * @brief Callback function called when PA completed an operation
* @param ctx Context which operation has succeeded
- * @param success The success value for the operation (ignored)
+ * @param nbytes the number of bytes PA requested
+ * @param this_gen pulse_driver_t pointer for the PulseAudio output
+ * instance.
+ */
+static void __xine_pa_stream_success_callback(pa_stream *s, int success, void *this_gen)
+{
+ pulse_driver_t * this = (pulse_driver_t*) this_gen;
+
+ if (!success)
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: stream operation failed: %s\n", pa_strerror(pa_context_errno(this->context)));
+
+ pa_threaded_mainloop_signal(this->mainloop, 0);
+}
+
+/**
+ * @brief Callback function called when PA completed an operation
+ * @param c Context on which operation has succeeded
+ * @param nbytes the number of bytes PA requested
* @param this_gen pulse_driver_t pointer for the PulseAudio output
* instance.
*/
-static void __xine_pa_context_success_callback(pa_context *const ctx, const int success,
- void *const this_gen)
+static void __xine_pa_context_success_callback(pa_context *c, int success, void *this_gen)
{
- pulse_driver_t *const this = (pulse_driver_t*)this_gen;
+ pulse_driver_t *this = (pulse_driver_t*) this_gen;
- _x_assert(ctx); _x_assert(this);
- _x_assert(ctx == this->pa_class->context);
+ if (!success)
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: context operation failed: %s\n", pa_strerror(pa_context_errno(this->context)));
- pa_threaded_mainloop_signal(this->pa_class->mainloop, 0);
+ pa_threaded_mainloop_signal(this->mainloop, 0);
}
/**
@@ -156,14 +202,14 @@ static void __xine_pa_context_success_callback(pa_context *const ctx, const int
* This function saves the volume field of the passed structure to the
* @c cvolume variable of the output instance.
*/
-static void __xine_pa_sink_info_callback(pa_context *const ctx, const pa_sink_input_info *const info,
- const int is_last, void *const userdata) {
+static void __xine_pa_sink_info_callback(pa_context *c, const pa_sink_input_info *info,
+ int is_last, void *userdata) {
pulse_driver_t *const this = (pulse_driver_t *) userdata;
if (is_last < 0) {
xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: Failed to get sink input info: %s\n",
- pa_strerror(pa_context_errno(this->pa_class->context)));
+ pa_strerror(pa_context_errno(this->context)));
return;
}
@@ -171,36 +217,95 @@ static void __xine_pa_sink_info_callback(pa_context *const ctx, const pa_sink_in
return;
this->cvolume = info->volume;
+ this->swvolume = pa_cvolume_avg(&info->volume);
+#if PA_PROTOCOL_VERSION >= 11
+ /* PulseAudio 0.9.7 and newer */
+ this->muted = info->mute;
+#else
+ this->muted = pa_cvolume_is_muted (&this->cvolume);
+#endif
+}
+
+static int connect_context(pulse_driver_t *this) {
+
+ if (this->context && (pa_context_get_state(this->context) == PA_CONTEXT_FAILED ||
+ pa_context_get_state(this->context) == PA_CONTEXT_TERMINATED)) {
+ pa_context_unref(this->context);
+ this->context = NULL;
+ }
+
+ if (!this->context) {
+ char fn[XINE_PATH_MAX], *p;
+
+ if (pa_get_binary_name(fn, sizeof(fn)))
+ p = pa_path_get_filename(fn);
+ else
+ p = "Xine";
- pthread_mutex_unlock(&this->info_mutex);
+ this->context = pa_context_new(pa_threaded_mainloop_get_api(this->mainloop), p);
+ _x_assert(this->context);
+
+ pa_context_set_state_callback(this->context, __xine_pa_context_state_callback, this);
+ }
+
+ if (pa_context_get_state(this->context) == PA_CONTEXT_UNCONNECTED) {
+
+ if (pa_context_connect(this->context, this->host, 0, NULL) < 0) {
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: failed to connect context object %s\n", pa_strerror(pa_context_errno(this->context)));
+ return -1;
+ }
+ }
+
+ for (;;) {
+ pa_context_state_t state = pa_context_get_state(this->context);
+
+ if (state == PA_CONTEXT_FAILED || state == PA_CONTEXT_TERMINATED) {
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: failed to connect context object: %s\n", pa_strerror(pa_context_errno(this->context)));
+ return -1;
+ }
+
+ if (state == PA_CONTEXT_READY)
+ break;
+
+ pa_threaded_mainloop_wait(this->mainloop);
+ }
+
+ return 0;
}
/*
* open the audio device for writing to
*/
static int ao_pulse_open(ao_driver_t *this_gen,
- uint32_t bits, uint32_t rate, int mode)
+ uint32_t bits, uint32_t rate, int mode)
{
pulse_driver_t *this = (pulse_driver_t *) this_gen;
- struct pa_sample_spec ss;
- struct pa_buffer_attr a;
- pa_stream_state_t streamstate;
+ pa_sample_spec ss;
+ pa_channel_map cm;
+ int r;
xprintf (this->xine, XINE_VERBOSITY_DEBUG,
- "audio_pulse_out: ao_open bits=%d rate=%d, mode=%d\n", bits, rate, mode);
+ "audio_pulse_out: ao_open bits=%d rate=%d, mode=%d\n", bits, rate, mode);
if ( (mode & this->capabilities) == 0 ) {
xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: unsupported mode %08x\n", mode);
return 0;
}
+ pa_threaded_mainloop_lock(this->mainloop);
+
if (this->stream) {
- if ( mode == this->mode && rate == this->sample_rate &&
- bits == this->bits_per_sample )
+ if (mode == this->mode && rate == this->sample_rate &&
+ bits == this->bits_per_sample) {
+
+ pa_threaded_mainloop_unlock(this->mainloop);
return this->sample_rate;
+ }
- this_gen->close(this_gen);
+ pa_stream_disconnect(this->stream);
+ pa_stream_unref(this->stream);
+ this->stream = NULL;
}
this->mode = mode;
@@ -221,6 +326,8 @@ static int ao_pulse_open(ao_driver_t *this_gen,
case 32:
ss.format = PA_SAMPLE_FLOAT32NE;
break;
+ default:
+ _x_assert(!"Should not be reached");
}
if (!pa_sample_spec_valid(&ss)) {
@@ -228,69 +335,86 @@ static int ao_pulse_open(ao_driver_t *this_gen,
goto fail;
}
- if ( this->pa_class->context && pa_context_get_state(this->pa_class->context) > PA_CONTEXT_READY ) {
- pa_context_unref(this->pa_class->context);
- this->pa_class->context = NULL;
- }
-
- if ( this->pa_class->context == NULL ) {
- this->pa_class->context = pa_context_new(pa_threaded_mainloop_get_api(this->pa_class->mainloop),
- __progname);
- }
-
- pa_context_ref(this->pa_class->context);
+ cm.channels = ss.channels;
- if ( pa_context_get_state(this->pa_class->context) == PA_CONTEXT_UNCONNECTED ) {
- int ret;
+ switch (mode) {
+ case AO_CAP_MODE_MONO:
+ cm.map[0] = PA_CHANNEL_POSITION_MONO;
+ _x_assert(cm.channels == 1);
+ break;
- pa_threaded_mainloop_lock(this->pa_class->mainloop);
- ret = pa_context_connect(this->pa_class->context, this->host, 1, NULL);
- if ( ret < 0 )
- goto fail;
+ case AO_CAP_MODE_STEREO:
+ cm.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
+ cm.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
+ _x_assert(cm.channels == 2);
+ break;
- pa_context_set_state_callback(this->pa_class->context, __xine_pa_context_status_callback, this);
+ case AO_CAP_MODE_4CHANNEL:
+ cm.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
+ cm.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
+ cm.map[2] = PA_CHANNEL_POSITION_REAR_LEFT;
+ cm.map[3] = PA_CHANNEL_POSITION_REAR_RIGHT;
+ _x_assert(cm.channels == 4);
+ break;
- pa_threaded_mainloop_wait(this->pa_class->mainloop);
- pa_threaded_mainloop_unlock(this->pa_class->mainloop);
+ case AO_CAP_MODE_4_1CHANNEL:
+ case AO_CAP_MODE_5CHANNEL:
+ case AO_CAP_MODE_5_1CHANNEL:
+ cm.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
+ cm.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
+ cm.map[2] = PA_CHANNEL_POSITION_REAR_LEFT;
+ cm.map[3] = PA_CHANNEL_POSITION_REAR_RIGHT;
+ cm.map[4] = PA_CHANNEL_POSITION_FRONT_CENTER;
+ cm.map[5] = PA_CHANNEL_POSITION_LFE;
+ cm.channels = 6;
+ break;
+ default:
+ _x_assert(!"Should not be reached");
}
- if (pa_context_get_state(this->pa_class->context) != PA_CONTEXT_READY) {
- xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: Failed to connect to server: %s\n",
- pa_strerror(pa_context_errno(this->pa_class->context)));
+ if (!pa_channel_map_valid(&cm)) {
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: Invalid channel map\n");
goto fail;
}
- this->stream = pa_stream_new(this->pa_class->context, "audio stream", &ss, NULL);
+ if (connect_context(this) < 0)
+ goto fail;
+
+ _x_assert(!this->stream);
+ this->stream = pa_stream_new(this->context, "Audio Stream", &ss, &cm);
_x_assert(this->stream);
- a.maxlength = pa_bytes_per_second(&ss)*1;
- a.tlength = a.maxlength*9/10;
- a.prebuf = a.tlength/2;
- a.minreq = a.tlength/10;
+ pa_stream_set_state_callback(this->stream, __xine_pa_stream_state_callback, this);
+ pa_stream_set_write_callback(this->stream, __xine_pa_stream_request_callback, this);
+ pa_stream_set_latency_update_callback(this->stream, __xine_pa_stream_notify_callback, this);
- pa_stream_connect_playback(this->stream, this->sink, &a,
- PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE,
+ r = pa_stream_connect_playback(this->stream, this->sink, NULL,
+ PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE,
NULL, NULL);
- do {
- xine_usec_sleep (100);
+ for (;;) {
+ pa_context_state_t cstate = pa_context_get_state(this->context);
+ pa_stream_state_t sstate = pa_stream_get_state(this->stream);
- streamstate = pa_stream_get_state(this->stream);
- } while (streamstate < PA_STREAM_READY);
-
- if (streamstate != PA_STREAM_READY) {
- xprintf (this->xine, XINE_VERBOSITY_LOG, "audio_pulse_out: Failed to connect to server: %s\n",
- pa_strerror(pa_context_errno(this->pa_class->context)));
- goto fail;
+ if (cstate == PA_CONTEXT_FAILED || cstate == PA_CONTEXT_TERMINATED ||
+ sstate == PA_STREAM_FAILED || sstate == PA_STREAM_TERMINATED) {
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: failed to connect context object: %s\n", pa_strerror(pa_context_errno(this->context)));
+ goto fail;
+ }
+
+ if (sstate == PA_STREAM_READY)
+ break;
+
+ pa_threaded_mainloop_wait(this->mainloop);
}
- this->frames_written = 0;
- this->ao_driver.set_property(this, AO_PROP_PCM_VOL, 100);
+ pa_threaded_mainloop_unlock(this->mainloop);
return this->sample_rate;
-fail:
- pa_threaded_mainloop_unlock(this->pa_class->mainloop);
+ fail:
+
+ pa_threaded_mainloop_unlock(this->mainloop);
this_gen->close(this_gen);
return 0;
}
@@ -318,217 +442,367 @@ static int ao_pulse_write(ao_driver_t *this_gen, int16_t *data,
{
pulse_driver_t *this = (pulse_driver_t *) this_gen;
size_t size = num_frames * this->bytes_per_frame;
- int ret = 0;
-
- if ( !this->stream || !this->pa_class->context)
- return -1;
+ int ret = -1;
+ size_t done = 0;
- switch( pa_stream_get_state(this->stream) ) {
- case PA_STREAM_READY:
- while (size > 0) {
- size_t l;
+ pa_threaded_mainloop_lock(this->mainloop);
- while (!(l = pa_stream_writable_size(this->stream))) {
- xine_usec_sleep (10000);
- }
+ while (size > 0) {
+ size_t l;
- if (l > size)
- l = size;
-
- pa_stream_write(this->stream, data, l, NULL, 0, PA_SEEK_RELATIVE);
- data = (int16_t *) ((uint8_t*) data + l);
- size -= l;
- }
+ for (;;) {
+
+ if (!this->stream ||
+ !this->context ||
+ pa_context_get_state(this->context) != PA_CONTEXT_READY ||
+ pa_stream_get_state(this->stream) != PA_STREAM_READY)
+ goto finish;
- this->frames_written += num_frames;
+ if ((l = pa_stream_writable_size(this->stream)) == (size_t) -1)
+ goto finish;
- if (pa_stream_get_state(this->stream) == PA_STREAM_READY)
- ret = 1;
+ if (l > 0)
+ break;
- break;
+ pa_threaded_mainloop_wait(this->mainloop);
+ }
+
+ if (l > size)
+ l = size;
+
+ pa_stream_write(this->stream, data, l, NULL, 0, PA_SEEK_RELATIVE);
+ data = (int16_t *) ((uint8_t*) data + l);
+ size -= l;
+ done += l;
}
+ ret = done;
+
+finish:
+
+ pa_threaded_mainloop_unlock(this->mainloop);
+
+/* fprintf(stderr, "write-out\n"); */
+
return ret;
-}
+}
static int ao_pulse_delay (ao_driver_t *this_gen)
{
pulse_driver_t *this = (pulse_driver_t *) this_gen;
- pa_usec_t latency = 0;
- unsigned int delay_frames;
+ int ret = 0;
- if ( ! this->stream ) return this->frames_written;
+/* fprintf(stderr, "delay-in\n"); */
- if (pa_stream_get_latency(this->stream, &latency, NULL) < 0) {
- pa_context_unref(this->pa_class->context);
- this->pa_class->context = NULL;
+ pa_threaded_mainloop_lock(this->mainloop);
- pa_stream_disconnect(this->stream);
- pa_stream_unref(this->stream);
- this->stream = NULL;
+ for (;;) {
+ pa_usec_t latency = 0;
- return 0;
+ if (!this->stream ||
+ !this->context ||
+ pa_context_get_state(this->context) != PA_CONTEXT_READY ||
+ pa_stream_get_state(this->stream) != PA_STREAM_READY)
+ goto finish;
+
+ if (pa_stream_get_latency(this->stream, &latency, NULL) >= 0) {
+ ret = (int) ((latency * this->sample_rate) / 1000000);
+ goto finish;
+ }
+
+ if (pa_context_errno(this->context) != PA_ERR_NODATA) {
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: failed to query latency: %s\n", pa_strerror(pa_context_errno(this->context)));
+ goto finish;
+ }
+
+ pa_threaded_mainloop_wait(this->mainloop);
}
- /* convert latency (us) to frame units. */
- delay_frames = (int)(latency * this->sample_rate / 1000000);
+finish:
+
+ pa_threaded_mainloop_unlock(this->mainloop);
- if( delay_frames > this->frames_written )
- return this->frames_written;
- else
- return delay_frames;
+ return ret;
}
static void ao_pulse_close(ao_driver_t *this_gen)
{
pulse_driver_t *this = (pulse_driver_t *) this_gen;
-
- if (this->stream) {
- if (pa_stream_get_state(this->stream) == PA_STREAM_READY) {
- pthread_mutex_t completion_callback = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock(&completion_callback);
- pa_stream_drain(this->stream, __xine_pa_stream_success_callback, &completion_callback);
- pthread_mutex_lock(&completion_callback);
- pthread_mutex_destroy(&completion_callback);
- }
+ pa_threaded_mainloop_lock(this->mainloop);
+ if (this->stream) {
pa_stream_disconnect(this->stream);
pa_stream_unref(this->stream);
this->stream = NULL;
-
- pa_context_unref(this->pa_class->context);
}
+
+ pa_threaded_mainloop_unlock(this->mainloop);
}
static uint32_t ao_pulse_get_capabilities (ao_driver_t *this_gen) {
pulse_driver_t *this = (pulse_driver_t *) this_gen;
+
return this->capabilities;
}
-static void ao_pulse_exit(ao_driver_t *this_gen)
-{
+static void ao_pulse_exit(ao_driver_t *this_gen) {
pulse_driver_t *this = (pulse_driver_t *) this_gen;
- free (this);
+ ao_pulse_close(this_gen);
+
+ pa_threaded_mainloop_lock(this->mainloop);
+
+ if (this->context) {
+ pa_context_disconnect(this->context);
+ pa_context_unref(this->context);
+ }
+
+ pa_threaded_mainloop_unlock(this->mainloop);
+
+ pa_threaded_mainloop_free(this->mainloop);
+
+ free(this->host);
+ free(this->sink);
+ free(this);
+}
+
+static int wait_for_operation(pulse_driver_t *this, pa_operation *o) {
+
+ for (;;) {
+
+ if (!this->stream ||
+ !this->context ||
+ pa_context_get_state(this->context) != PA_CONTEXT_READY ||
+ pa_stream_get_state(this->stream) != PA_STREAM_READY)
+ return -1;
+
+ if (pa_operation_get_state(o) != PA_OPERATION_RUNNING)
+ return 0;
+
+ pa_threaded_mainloop_wait(this->mainloop);
+ }
}
static int ao_pulse_get_property (ao_driver_t *this_gen, int property) {
pulse_driver_t *this = (pulse_driver_t *) this_gen;
int result = 0;
+ pa_operation *o = NULL;
- if ( ! this->stream || ! this->pa_class->context )
+ pa_threaded_mainloop_lock(this->mainloop);
+
+ if (!this->stream ||
+ !this->context ||
+ pa_context_get_state(this->context) != PA_CONTEXT_READY ||
+ pa_stream_get_state(this->stream) != PA_STREAM_READY) {
+ pa_threaded_mainloop_unlock(this->mainloop);
return 0;
+ }
switch(property) {
- case AO_PROP_PCM_VOL:
- case AO_PROP_MIXER_VOL:
- {
- pthread_mutex_lock(&this->info_mutex);
- pa_operation *o = pa_context_get_sink_input_info(this->pa_class->context,
- pa_stream_get_index(this->stream),
- __xine_pa_sink_info_callback, this);
- if ( ! o ) return 0;
- pthread_mutex_lock(&this->info_mutex); pthread_mutex_unlock(&this->info_mutex);
-
- result = (pa_sw_volume_to_linear(this->swvolume)*100);
- }
- break;
- case AO_PROP_MUTE_VOL:
- result = pa_cvolume_is_muted(&this->cvolume);
- break;
+ case AO_PROP_MUTE_VOL:
+ case AO_PROP_PCM_VOL:
+ case AO_PROP_MIXER_VOL:
+
+ o = pa_context_get_sink_input_info(this->context, pa_stream_get_index(this->stream),
+ __xine_pa_sink_info_callback, this);
+
+ break;
+ }
+
+ if (o) {
+ wait_for_operation(this, o);
+ pa_operation_unref(o);
+ }
+
+ switch(property) {
+
+ case AO_PROP_MUTE_VOL:
+ result = this->muted;
+ break;
+
+ case AO_PROP_PCM_VOL:
+ case AO_PROP_MIXER_VOL:
+ result = (int) (pa_sw_volume_to_linear(this->swvolume)*100);
+ break;
}
-
+
+ pa_threaded_mainloop_unlock(this->mainloop);
+
return result;
}
static int ao_pulse_set_property (ao_driver_t *this_gen, int property, int value) {
pulse_driver_t *this = (pulse_driver_t *) this_gen;
int result = ~value;
+ pa_operation *o = NULL;
- if ( ! this->stream || ! this->pa_class->context )
- return result;
+ pa_threaded_mainloop_lock(this->mainloop);
+
+ if (!this->stream ||
+ !this->context ||
+ pa_context_get_state(this->context) != PA_CONTEXT_READY ||
+ pa_stream_get_state(this->stream) != PA_STREAM_READY) {
+ pa_threaded_mainloop_unlock(this->mainloop);
+ return 0;
+ }
switch(property) {
- case AO_PROP_PCM_VOL:
- case AO_PROP_MIXER_VOL:
- this->swvolume = pa_sw_volume_from_linear((double)value/100.0);
- pa_cvolume_set(&this->cvolume, pa_stream_get_sample_spec(this->stream)->channels, this->swvolume);
+ case AO_PROP_PCM_VOL:
+ case AO_PROP_MIXER_VOL:
+
+ this->swvolume = pa_sw_volume_from_linear((double)value/100.0);
+ pa_cvolume_set(&this->cvolume, pa_stream_get_sample_spec(this->stream)->channels, this->swvolume);
- pa_context_set_sink_input_volume(this->pa_class->context, pa_stream_get_index(this->stream),
- &this->cvolume, __xine_pa_context_success_callback, this);
+ o = pa_context_set_sink_input_volume(this->context, pa_stream_get_index(this->stream),
+ &this->cvolume, __xine_pa_context_success_callback, this);
- result = value;
- break;
+ result = value;
+ break;
- case AO_PROP_MUTE_VOL:
- if ( value )
- pa_cvolume_mute(&this->cvolume, pa_stream_get_sample_spec(this->stream)->channels);
- else
- pa_cvolume_set(&this->cvolume, pa_stream_get_sample_spec(this->stream)->channels, this->swvolume);
+ case AO_PROP_MUTE_VOL:
- pa_context_set_sink_input_volume(this->pa_class->context, pa_stream_get_index(this->stream),
- &this->cvolume, __xine_pa_context_success_callback, this);
-
- result = value;
- break;
+ this->muted = value;
+
+#if PA_PROTOCOL_VERSION >= 11
+ /* PulseAudio 0.9.7 and newer */
+ o = pa_context_set_sink_input_mute(this->context, pa_stream_get_index(this->stream),
+ value, __xine_pa_context_success_callback, this);
+#else
+ /* Get the current volume, so we can restore it properly. */
+ o = pa_context_get_sink_input_info(this->context, pa_stream_get_index(this->stream),
+ __xine_pa_sink_info_callback, this);
+
+ if (o) {
+ wait_for_operation(this, o);
+ pa_operation_unref(o);
+ }
+
+ if ( value )
+ pa_cvolume_mute(&this->cvolume, pa_stream_get_sample_spec(this->stream)->channels);
+ else
+ pa_cvolume_set(&this->cvolume, pa_stream_get_sample_spec(this->stream)->channels, this->swvolume);
+
+ o = pa_context_set_sink_input_volume(this->context, pa_stream_get_index(this->stream),
+ &this->cvolume, __xine_pa_context_success_callback, this);
+#endif
+ result = value;
}
-
+
+ if (o) {
+ wait_for_operation(this, o);
+ pa_operation_unref(o);
+ }
+
+ pa_threaded_mainloop_unlock(this->mainloop);
+
return result;
}
static int ao_pulse_ctrl(ao_driver_t *this_gen, int cmd, ...) {
pulse_driver_t *this = (pulse_driver_t *) this_gen;
+ pa_operation *o = NULL;
- if ( ! this->stream ) return 0;
+ pa_threaded_mainloop_lock(this->mainloop);
+
+ if (!this->stream ||
+ !this->context ||
+ pa_context_get_state(this->context) != PA_CONTEXT_READY ||
+ pa_stream_get_state(this->stream) != PA_STREAM_READY) {
+ pa_threaded_mainloop_unlock(this->mainloop);
+ return 0;
+ }
switch (cmd) {
- case AO_CTRL_FLUSH_BUFFERS:
- _x_assert(this->stream && this->pa_class->context);
+ case AO_CTRL_FLUSH_BUFFERS:
- if(pa_stream_get_state(this->stream) == PA_STREAM_READY) {
- pthread_mutex_t completion_callback = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock(&completion_callback);
- pa_stream_flush(this->stream, __xine_pa_stream_success_callback, &completion_callback);
+ o = pa_stream_flush(this->stream, __xine_pa_stream_success_callback, this);
+ break;
- pthread_mutex_lock(&completion_callback);
- pthread_mutex_destroy(&completion_callback);
- }
+ case AO_CTRL_PLAY_RESUME:
+ case AO_CTRL_PLAY_PAUSE:
- this->frames_written = 0;
+ o = pa_stream_cork(this->stream, cmd == AO_CTRL_PLAY_PAUSE, __xine_pa_stream_success_callback, this);
+ break;
+ }
- break;
+ if (o) {
+ wait_for_operation(this, o);
+ pa_operation_unref(o);
}
+ pa_threaded_mainloop_unlock(this->mainloop);
+
return 0;
}
static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *data) {
pulse_class_t *class = (pulse_class_t *) class_gen;
pulse_driver_t *this;
- char *device;
+ const char* device;
+ int r;
lprintf ("audio_pulse_out: open_plugin called\n");
- this = (pulse_driver_t *) xine_xmalloc (sizeof (pulse_driver_t));
+ this = calloc(1, sizeof (pulse_driver_t));
if (!this)
return NULL;
+
this->xine = class->xine;
+ this->host = NULL;
+ this->sink = NULL;
+ this->context = NULL;
+ this->mainloop = NULL;
+
+ device = class->xine->config->register_string(class->xine->config,
+ "audio.pulseaudio_device",
+ "",
+ _("device used for pulseaudio"),
+ _("use 'server[:sink]' for setting the "
+ "pulseaudio sink device."),
+ 10, NULL,
+ NULL);
+
+ if (device && *device) {
+ char *sep = strrchr(device, ':');
+ if ( sep ) {
+ if (!(this->host = strndup(device, sep-device))) {
+ free(this);
+ return NULL;
+ }
+
+ if (!(this->sink = strdup(sep+1))) {
+ free(this->host);
+ free(this);
+ return NULL;
+ }
+ } else {
+
+ if (!(this->host = strdup(device))) {
+ free(this);
+ return NULL;
+ }
+ }
+ }
+
+ this->mainloop = pa_threaded_mainloop_new();
+ _x_assert(this->mainloop);
+ pa_threaded_mainloop_start(this->mainloop);
/*
* set capabilities
*/
- this->capabilities = AO_CAP_MODE_MONO | AO_CAP_MODE_STEREO | AO_CAP_MODE_4CHANNEL |
- AO_CAP_MODE_4_1CHANNEL | AO_CAP_MODE_5CHANNEL |
- AO_CAP_MODE_5_1CHANNEL | AO_CAP_MIXER_VOL |
- AO_CAP_PCM_VOL | AO_CAP_MUTE_VOL | AO_CAP_8BITS |
- AO_CAP_16BITS | AO_CAP_FLOAT32;
+ this->capabilities =
+ AO_CAP_MODE_MONO | AO_CAP_MODE_STEREO | AO_CAP_MODE_4CHANNEL |
+ AO_CAP_MODE_4_1CHANNEL | AO_CAP_MODE_5CHANNEL | AO_CAP_MODE_5_1CHANNEL |
+ AO_CAP_MIXER_VOL | AO_CAP_PCM_VOL | AO_CAP_MUTE_VOL |
+ AO_CAP_8BITS | AO_CAP_16BITS | AO_CAP_FLOAT32;
this->sample_rate = 0;
- this->host = NULL;
- this->sink = NULL;
-
+
this->ao_driver.get_capabilities = ao_pulse_get_capabilities;
this->ao_driver.get_property = ao_pulse_get_property;
this->ao_driver.set_property = ao_pulse_set_property;
@@ -540,33 +814,22 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da
this->ao_driver.close = ao_pulse_close;
this->ao_driver.exit = ao_pulse_exit;
this->ao_driver.get_gap_tolerance = ao_pulse_get_gap_tolerance;
- this->ao_driver.control = ao_pulse_ctrl;
-
- device = this->xine->config->register_string(this->xine->config,
- "audio.pulseaudio_device",
- "",
- _("device used for pulseaudio"),
- _("use 'server[:sink]' for setting the "
- "pulseaudio sink device."),
- 10, NULL,
- NULL);
-
- if (device && *device) {
- char *sep = strchr(device, ':');
- if ( sep ) {
- this->host = strndup(device, sep-device);
- this->sink = strdup(&sep[1]);
- } else
- this->host = strdup(device);
- }
-
- pthread_mutex_init(&this->info_mutex, NULL);
+ this->ao_driver.control = ao_pulse_ctrl;
xprintf (class->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: host %s sink %s\n",
this->host ? this->host : "(null)", this->sink ? this->sink : "(null)");
this->pa_class = class;
+ pa_threaded_mainloop_lock(this->mainloop);
+ r = connect_context(this);
+ pa_threaded_mainloop_unlock(this->mainloop);
+
+ if (r < 0) {
+ ao_pulse_exit((ao_driver_t *) this);
+ return NULL;
+ }
+
return &this->ao_driver;
}
@@ -586,13 +849,7 @@ static void dispose_class (audio_driver_class_t *this_gen) {
pulse_class_t *this = (pulse_class_t *) this_gen;
- if ( this->context )
- pa_context_unref(this->context);
-
- pa_threaded_mainloop_stop(this->mainloop);
- pa_threaded_mainloop_free(this->mainloop);
-
- free (this);
+ free(this);
}
static void *init_class (xine_t *xine, void *data) {
@@ -601,29 +858,21 @@ static void *init_class (xine_t *xine, void *data) {
lprintf ("audio_pulse_out: init class\n");
- this = (pulse_class_t *) xine_xmalloc (sizeof (pulse_class_t));
+ this = calloc(1, sizeof (pulse_class_t));
if (!this)
return NULL;
+ this->xine = xine;
this->driver_class.open_plugin = open_plugin;
this->driver_class.get_identifier = get_identifier;
this->driver_class.get_description = get_description;
this->driver_class.dispose = dispose_class;
- this->xine = xine;
-
- this->mainloop = pa_threaded_mainloop_new();
- _x_assert(this->mainloop);
-
- pa_threaded_mainloop_start(this->mainloop);
-
- this->context = NULL;
-
return this;
}
static const ao_info_t ao_info_pulse = {
- 6
+ 12
};
/*
@@ -635,5 +884,3 @@ const plugin_info_t xine_plugin_info[] EXPORTED = {
{ PLUGIN_AUDIO_OUT, 8, "pulseaudio", XINE_VERSION_CODE, &ao_info_pulse, init_class },
{ PLUGIN_NONE, 0, "", 0, NULL, NULL }
};
-
-
diff --git a/src/audio_out/audio_sndio_out.c b/src/audio_out/audio_sndio_out.c
new file mode 100644
index 000000000..1d789b5e8
--- /dev/null
+++ b/src/audio_out/audio_sndio_out.c
@@ -0,0 +1,414 @@
+/*
+ * Copyright (c) 2008 Brad Smith <brad@comstyle.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* ao plugin for sndio by Brad Smith <brad@comstyle.com>. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <math.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <pthread.h>
+
+#include <sndio.h>
+
+#include "xine_internal.h"
+#include "xineutils.h"
+#include "audio_out.h"
+#include "bswap.h"
+
+#define GAP_TOLERANCE AO_MAX_GAP
+#define PCT_TO_MIDI(p) (((p) * SIO_MAXVOL + 50) / 100)
+
+typedef struct {
+ audio_driver_class_t driver_class;
+ xine_t *xine;
+} sndio_class_t;
+
+typedef struct sndio_driver_s {
+ ao_driver_t ao_driver;
+ xine_t *xine;
+
+ struct sio_hdl *hdl;
+ long long realpos, playpos;
+ int capabilities;
+
+ int num_channels;
+ u_int32_t bits_per_sample;
+ u_int32_t bytes_per_frame;
+
+ struct {
+ int volume;
+ int mute;
+ } mixer;
+} sndio_driver_t;
+
+/*
+ * Callback to notify of frames processed by the hw. It is
+ * called from the mail loop called from sio_write().
+ */
+static void ao_sndio_onmove_cb(void *addr, int delta)
+{
+ sndio_driver_t *this = (sndio_driver_t *)addr;
+
+ this->realpos += delta;
+}
+
+/*
+ * Open the audio device for writing to.
+ */
+static int ao_sndio_open(ao_driver_t *this_gen,
+ uint32_t bits, uint32_t rate, int mode)
+{
+ sndio_driver_t *this = (sndio_driver_t *) this_gen;
+ struct sio_par par;
+
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG,
+ "audio_sndio_out: ao_sndio_open bits=%d rate=%d, mode=%d\n",
+ bits, rate, mode);
+
+ if (this->hdl != NULL) {
+ sio_close (this->hdl);
+ this->hdl = NULL;
+ }
+
+ this->hdl = sio_open(NULL, SIO_PLAY, 0);
+ if (this->hdl == NULL)
+ goto bad;
+
+ sio_initpar(&par);
+
+ switch (mode) {
+ case AO_CAP_MODE_MONO:
+ par.pchan = 1;
+ break;
+ case AO_CAP_MODE_STEREO:
+ par.pchan = 2;
+ break;
+#if 0
+ case AO_CAP_MODE_4CHANNEL:
+ par.pchan = 4;
+ break;
+ case AO_CAP_MODE_4_1CHANNEL:
+ case AO_CAP_MODE_5CHANNEL:
+ case AO_CAP_MODE_5_1CHANNEL:
+ par.pchan = 6;
+ break;
+#endif
+ default:
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG,
+ "audio_sndio_out: ao_sndio_open does not support the requested mode: 0x%X\n",
+ mode);
+ goto bad;
+ }
+
+ switch (bits) {
+ case 8:
+ par.bits = 8;
+ par.sig = 0;
+ break;
+ case 16:
+ par.bits = 16;
+ par.sig = 1;
+ break;
+ default:
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG,
+ "audio_sndio_out: ao_sndio_open bits per sample not supported: %d\n", bits);
+ goto bad;
+ }
+
+ par.rate = rate;
+ par.appbufsz = par.rate * 250 / 1000; /* 250ms buffer */
+
+ if (!sio_setpar(this->hdl, &par)) {
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG,
+ "audio_sndio_out: ao_sndio_open could not set params\n");
+ goto bad;
+ }
+
+ if (!sio_getpar(this->hdl, &par)) {
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG,
+ "audio_sndio_out: ao_sndio_open could not get params\n");
+ goto bad;
+ }
+
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG,
+ "audio_sndio_out: ao_sndio_open %d channels output\n",
+ par.pchan);
+
+ this->num_channels = par.pchan;
+ this->bytes_per_frame = par.bps * par.pchan;
+ this->playpos = 0;
+ this->realpos = 0;
+ sio_onmove(this->hdl, ao_sndio_onmove_cb, this);
+
+ if (!sio_start(this->hdl)) {
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG,
+ "audio_sndio_out: ao_sndio_open could not start\n");
+ goto bad;
+ }
+
+ return par.rate;
+
+bad:
+ if (this->hdl != NULL)
+ sio_close(this->hdl);
+ return 0;
+}
+
+static int ao_sndio_num_channels(ao_driver_t *this_gen)
+{
+ sndio_driver_t *this = (sndio_driver_t *) this_gen;
+
+ return this->num_channels;
+}
+
+static int ao_sndio_bytes_per_frame(ao_driver_t *this_gen)
+{
+ sndio_driver_t *this = (sndio_driver_t *) this_gen;
+
+ return this->bytes_per_frame;
+}
+
+static int ao_sndio_get_gap_tolerance (ao_driver_t *this_gen)
+{
+ return GAP_TOLERANCE;
+}
+
+static int ao_sndio_write(ao_driver_t *this_gen, int16_t *data,
+ uint32_t num_frames)
+{
+ sndio_driver_t *this = (sndio_driver_t *) this_gen;
+ size_t ret, size = num_frames * this->bytes_per_frame;
+
+ ret = sio_write(this->hdl, data, size);
+ if (ret == 0)
+ return 0;
+
+ this->playpos += num_frames;
+
+ return 1;
+}
+
+static int ao_sndio_delay (ao_driver_t *this_gen)
+{
+ sndio_driver_t *this = (sndio_driver_t *) this_gen;
+ int bufused;
+
+ if (this->realpos < 0)
+ bufused = this->playpos;
+ else
+ bufused = this->playpos - this->realpos;
+
+ return bufused;
+}
+
+static void ao_sndio_close(ao_driver_t *this_gen)
+{
+ sndio_driver_t *this = (sndio_driver_t *) this_gen;
+
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG,
+ "audio_sndio_out: ao_sndio_close called\n");
+
+ if (!sio_stop(this->hdl)) {
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG,
+ "audio_sndio_out: ao_sndio_close could not stop\n");
+ }
+
+ sio_close(this->hdl);
+ this->hdl = NULL;
+}
+
+static uint32_t ao_sndio_get_capabilities (ao_driver_t *this_gen)
+{
+ sndio_driver_t *this = (sndio_driver_t *) this_gen;
+
+ return this->capabilities;
+}
+
+static void ao_sndio_exit(ao_driver_t *this_gen)
+{
+ sndio_driver_t *this = (sndio_driver_t *) this_gen;
+
+ xprintf (this->xine, XINE_VERBOSITY_DEBUG,
+ "audio_sndio_out: ao_sndio_exit called\n");
+
+ if (this->hdl != NULL)
+ sio_close(this->hdl);
+}
+
+static int ao_sndio_get_property (ao_driver_t *this_gen, int property)
+{
+ sndio_driver_t *this = (sndio_driver_t *) this_gen;
+
+ switch (property) {
+ case AO_PROP_MIXER_VOL:
+ return this->mixer.volume;
+ break;
+ case AO_PROP_MUTE_VOL:
+ return this->mixer.mute;
+ break;
+ }
+
+ return 0;
+}
+
+static int ao_sndio_set_property (ao_driver_t *this_gen, int property, int value)
+{
+ sndio_driver_t *this = (sndio_driver_t *) this_gen;
+ int vol;
+
+ if (this->hdl == NULL)
+ return 0;
+
+ switch(property) {
+ case AO_PROP_MIXER_VOL:
+ this->mixer.volume = value;
+ if (!this->mixer.mute)
+ sio_setvol(this->hdl, PCT_TO_MIDI(this->mixer.volume));
+ return this->mixer.volume;
+ break;
+
+ case AO_PROP_MUTE_VOL:
+ this->mixer.mute = (value) ? 1 : 0;
+ vol = 0;
+ if (!this->mixer.mute)
+ vol = PCT_TO_MIDI(this->mixer.volume);
+ sio_setvol(this->hdl, vol);
+ return value;
+ break;
+ }
+
+ return value;
+}
+
+/*
+ * pause, resume, flush buffers
+ */
+static int ao_sndio_ctrl(ao_driver_t *this_gen, int cmd, ...)
+{
+ sndio_driver_t *this = (sndio_driver_t *) this_gen;
+
+ /*
+ * sndio pauses automatically if there are no more samples to play
+ * and resumes when there are samples again. So we leave this empty
+ * for the moment.
+ */
+
+ return 0;
+}
+
+static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *data)
+{
+ sndio_class_t *class = (sndio_class_t *) class_gen;
+ sndio_driver_t *this;
+
+ lprintf ("audio_sndio_out: open_plugin called\n");
+
+ this = calloc(1, sizeof (sndio_driver_t));
+ if (!this)
+ return NULL;
+
+ this->xine = class->xine;
+
+ /*
+ * Set capabilities
+ */
+ this->capabilities = AO_CAP_MODE_MONO | AO_CAP_MODE_STEREO |
+#if 0
+ AO_CAP_MODE_4CHANNEL | AO_CAP_MODE_4_1CHANNEL |
+ AO_CAP_MODE_5CHANNEL | AO_CAP_MODE_5_1CHANNEL |
+#endif
+ AO_CAP_MIXER_VOL | AO_CAP_MUTE_VOL | AO_CAP_8BITS |
+ AO_CAP_16BITS;
+
+ this->ao_driver.get_capabilities = ao_sndio_get_capabilities;
+ this->ao_driver.get_property = ao_sndio_get_property;
+ this->ao_driver.set_property = ao_sndio_set_property;
+ this->ao_driver.open = ao_sndio_open;
+ this->ao_driver.num_channels = ao_sndio_num_channels;
+ this->ao_driver.bytes_per_frame = ao_sndio_bytes_per_frame;
+ this->ao_driver.delay = ao_sndio_delay;
+ this->ao_driver.write = ao_sndio_write;
+ this->ao_driver.close = ao_sndio_close;
+ this->ao_driver.exit = ao_sndio_exit;
+ this->ao_driver.get_gap_tolerance = ao_sndio_get_gap_tolerance;
+ this->ao_driver.control = ao_sndio_ctrl;
+
+ return &this->ao_driver;
+}
+
+/*
+ * class functions
+ */
+
+static char* get_identifier (audio_driver_class_t *this_gen)
+{
+ return "sndio";
+}
+
+static char* get_description (audio_driver_class_t *this_gen)
+{
+ return _("xine audio output plugin using sndio audio devices/drivers ");
+}
+
+static void dispose_class (audio_driver_class_t *this_gen)
+{
+ sndio_class_t *this = (sndio_class_t *) this_gen;
+
+ free(this);
+}
+
+static void *init_class (xine_t *xine, void *data)
+{
+ sndio_class_t *this;
+
+ lprintf ("audio_sndio_out: init class\n");
+
+ this = calloc(1, sizeof (sndio_class_t));
+ if (!this)
+ return NULL;
+
+ this->driver_class.open_plugin = open_plugin;
+ this->driver_class.get_identifier = get_identifier;
+ this->driver_class.get_description = get_description;
+ this->driver_class.dispose = dispose_class;
+
+ this->xine = xine;
+
+ return this;
+}
+
+static const ao_info_t ao_info_sndio = {
+ 12
+};
+
+/*
+ * exported plugin catalog entry
+ */
+
+const plugin_info_t xine_plugin_info[] EXPORTED = {
+ /* type, API, "name", version, special_info, init_function */
+ { PLUGIN_AUDIO_OUT, 8, "sndio", XINE_VERSION_CODE, &ao_info_sndio, init_class },
+ { PLUGIN_NONE, 0, "", 0, NULL, NULL }
+};
diff --git a/src/audio_out/audio_sun_out.c b/src/audio_out/audio_sun_out.c
index b23955b77..2a154c09d 100644
--- a/src/audio_out/audio_sun_out.c
+++ b/src/audio_out/audio_sun_out.c
@@ -1,18 +1,18 @@
-/*
+/*
* Copyright (C) 2001-2003 the xine project
- *
+ *
* This file is part of xine, a free video player.
- *
+ *
* xine 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.
- *
+ *
* xine 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
@@ -159,7 +159,7 @@ static int realtime_samplecounter_available(xine_t *xine, char *dev)
silence = calloc(1, len);
if (silence == NULL)
goto error;
-
+
if ((fd = open(dev, O_WRONLY|O_NONBLOCK)) < 0)
goto error;
@@ -176,7 +176,7 @@ static int realtime_samplecounter_available(xine_t *xine, char *dev)
xprintf(xine, XINE_VERBOSITY_DEBUG, "rtsc: SETINFO failed\n");
goto error;
}
-
+
if (write(fd, silence, len) != len) {
xprintf(xine, XINE_VERBOSITY_DEBUG, "rtsc: write failed\n");
goto error;
@@ -195,7 +195,7 @@ static int realtime_samplecounter_available(xine_t *xine, char *dev)
delay.tv_sec = 0;
delay.tv_nsec = 10000000;
nanosleep(&delay, NULL);
-
+
gettimeofday(&end, NULL);
usec_delay = (end.tv_sec - start.tv_sec) * 1000000
+ end.tv_usec - start.tv_usec;
@@ -230,7 +230,7 @@ static int realtime_samplecounter_available(xine_t *xine, char *dev)
* sample counter increment from the soundcard driver of less than
* 2000 samples, we assume that the driver provides a useable realtime
* sample counter in the AUDIO_INFO play.samples field. Timing based
- * on sample counts should be much more accurate than counting whole
+ * on sample counts should be much more accurate than counting whole
* 16kbyte chunks.
*/
if (min_increment < 2000)
@@ -238,10 +238,10 @@ static int realtime_samplecounter_available(xine_t *xine, char *dev)
/*
printf("audio_sun_out: minimum sample counter increment per 10msec interval: %d\n"
- "\t%susing sample counter based timing code\n",
+ "\t%susing sample counter based timing code\n",
min_increment, rtsc_ok == RTSC_ENABLED ? "" : "not ");
*/
-
+
error:
if (silence != NULL) free(silence);
@@ -263,7 +263,7 @@ error:
}
-/*
+/*
* match the requested sample rate |sample_rate| against the
* sample rates supported by the audio device |dev|. Return
* a supported sample rate, it that sample rate is close to
@@ -294,7 +294,7 @@ find_close_samplerate_match(int dev, int sample_rate)
if (sr->flags & MIXER_SR_LIMITS) {
/*
- * HW can playback any rate between
+ * HW can playback any rate between
* sr->samp_rates[0] .. sr->samp_rates[1]
*/
free(sr);
@@ -340,7 +340,7 @@ find_close_samplerate_match(int dev, int sample_rate)
for (i = 0; audiocs_rates[i]; i++) {
err = abs(audiocs_rates[i] - sample_rate);
if (err == 0) {
- /*
+ /*
* exact supported sample rate match, no need to
* retry something elise
*/
@@ -385,7 +385,7 @@ find_highest_samplerate(int dev)
if (sr->flags & MIXER_SR_LIMITS) {
/*
- * HW can playback any rate between
+ * HW can playback any rate between
* sr->samp_rates[0] .. sr->samp_rates[1]
*/
max_rate = sr->samp_rates[1];
@@ -412,7 +412,7 @@ find_highest_samplerate(int dev)
* Implicit assumptions about audio format (bits/rate/mode):
*
* bits == 16: We always get 16-bit samples in native endian format,
- * using signed linear encoding
+ * using signed linear encoding
*
* bits == 8: 8-bit samples use unsigned linear encoding,
* other 8-bit formats (uLaw, aLaw, etc) are currently not supported
@@ -440,7 +440,7 @@ static int ao_sun_open(ao_driver_t *this_gen,
close (this->audio_fd);
}
-
+
this->mode = mode;
this->input_sample_rate = rate;
#ifdef __svr4__
@@ -453,11 +453,11 @@ static int ao_sun_open(ao_driver_t *this_gen,
this->audio_fd = open(this->audio_dev, O_WRONLY|O_NONBLOCK);
if(this->audio_fd < 0) {
- xprintf(this->xine, XINE_VERBOSITY_LOG,
+ xprintf(this->xine, XINE_VERBOSITY_LOG,
_("audio_sun_out: opening audio device %s failed: %s\n"), this->audio_dev, strerror(errno));
return 0;
}
-
+
/* We wanted non blocking open but now put it back to normal */
fcntl(this->audio_fd, F_SETFL, fcntl(this->audio_fd, F_GETFL) & ~O_NONBLOCK);
@@ -485,7 +485,7 @@ static int ao_sun_open(ao_driver_t *this_gen,
if (pass & 1) {
/*
- * on some sun audio drivers, 8-bit unsigned LINEAR8 encoding is
+ * on some sun audio drivers, 8-bit unsigned LINEAR8 encoding is
* not supported, but 8-bit signed encoding is.
*
* Try S8, and if it works, use our own U8->S8 conversion before
@@ -511,7 +511,7 @@ static int ao_sun_open(ao_driver_t *this_gen,
*/
if (!(info.play.sample_rate =
find_close_samplerate_match(this->audio_fd,
- this->input_sample_rate)))
+ this->input_sample_rate)))
continue;
}
@@ -567,7 +567,7 @@ static int ao_sun_open(ao_driver_t *this_gen,
return this->output_sample_rate;
}
-static int ao_sun_num_channels(ao_driver_t *this_gen)
+static int ao_sun_num_channels(ao_driver_t *this_gen)
{
sun_driver_t *this = (sun_driver_t *) this_gen;
return this->num_channels;
@@ -589,7 +589,7 @@ static int ao_sun_delay(ao_driver_t *this_gen)
(this->frames_in_buffer == 0 || info.play.samples > 0)) {
if (info.play.samples < this->last_samplecnt) {
- xprintf(this->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->xine, XINE_VERBOSITY_DEBUG,
"audio_sun_out: broken sound driver, sample counter runs backwards, cur %u < prev %u\n",
info.play.samples, this->last_samplecnt);
}
@@ -728,7 +728,7 @@ static int ao_sun_write(ao_driver_t *this_gen,
int num_written;
if (this->convert_u8_s8) {
- /*
+ /*
* Audio hardware does not support 8-bit unsigned format,
* only 8-bit signed. Convert to 8-bit unsigned before sending
* the data to the audio device.
@@ -736,7 +736,7 @@ static int ao_sun_write(ao_driver_t *this_gen,
uint8_t *p = (void *)frame_buffer;
int i;
- for (i = num_frames * this->bytes_per_frame; --i >= 0; p++)
+ for (i = num_frames * this->bytes_per_frame; --i >= 0; p++)
*p ^= 0x80;
}
num_written = sun_audio_write(this, frame_buffer, num_frames * this->bytes_per_frame);
@@ -747,7 +747,7 @@ static int ao_sun_write(ao_driver_t *this_gen,
this->frames_in_buffer += num_written / this->bytes_per_frame;
#endif
- /*
+ /*
* Avoid storing too much data in the sound driver's buffers.
*
* When we find more than 3 seconds of buffered audio data in the
@@ -783,7 +783,7 @@ static uint32_t ao_sun_get_capabilities (ao_driver_t *this_gen) {
static void ao_sun_exit(ao_driver_t *this_gen)
{
sun_driver_t *this = (sun_driver_t *) this_gen;
-
+
if (this->audio_fd >= 0)
close(this->audio_fd);
@@ -869,7 +869,7 @@ static int ao_sun_ctrl(ao_driver_t *this_gen, int cmd, ...) {
/* flush buffered STEAMS data first */
ioctl(this->audio_fd, I_FLUSH, FLUSHW);
- /*
+ /*
* the flush above discarded an unknown amount of data from the
* audio device. To get the "*_delay" computation in sync again,
* reset the audio device's sample counter to 0, after waiting
@@ -909,7 +909,7 @@ static ao_driver_t *ao_sun_open_plugin (audio_driver_class_t *class_gen, const v
int status;
audio_info_t info;
- this = (sun_driver_t *) xine_xmalloc (sizeof (sun_driver_t));
+ this = calloc(1, sizeof (sun_driver_t));
if (!this)
return NULL;
@@ -944,7 +944,7 @@ static ao_driver_t *ao_sun_open_plugin (audio_driver_class_t *class_gen, const v
this->audio_fd = open(this->audio_dev = devname, O_WRONLY|O_NONBLOCK);
- if(this->audio_fd < 0)
+ if(this->audio_fd < 0)
{
xprintf(this->xine, XINE_VERBOSITY_LOG,
_("audio_sun_out: opening audio device %s failed: %s\n"), devname, strerror(errno));
@@ -962,7 +962,7 @@ static ao_driver_t *ao_sun_open_plugin (audio_driver_class_t *class_gen, const v
info.play.precision = AUDIO_PRECISION_16;
info.play.sample_rate = 44100;
status = ioctl(this->audio_fd, AUDIO_SETINFO, &info);
-
+
if (status < 0) {
xprintf(this->xine, XINE_VERBOSITY_LOG,
_("audio_sun_out: audio ioctl on device %s failed: %s\n"), devname, strerror(errno));
@@ -976,7 +976,7 @@ static ao_driver_t *ao_sun_open_plugin (audio_driver_class_t *class_gen, const v
*/
this->capabilities = AO_CAP_MODE_MONO | AO_CAP_MODE_STEREO | AO_CAP_8BITS
- | AO_CAP_16BITS | AO_CAP_PCM_VOL;
+ | AO_CAP_16BITS | AO_CAP_PCM_VOL;
#ifdef __svr4__
this->capabilities |= AO_CAP_MUTE_VOL;
#endif
@@ -1032,7 +1032,7 @@ static void ao_sun_dispose_class (audio_driver_class_t *this_gen) {
static void *ao_sun_init_class (xine_t *xine, void *data) {
sun_class_t *this;
- this = (sun_class_t *) xine_xmalloc (sizeof (sun_class_t));
+ this = calloc(1, sizeof (sun_class_t));
if (!this)
return NULL;
@@ -1056,7 +1056,7 @@ static const ao_info_t ao_info_sun = {
*/
const plugin_info_t xine_plugin_info[] EXPORTED = {
- /* type, API, "name", version, special_info, init_function */
+ /* type, API, "name", version, special_info, init_function */
{ PLUGIN_AUDIO_OUT, AO_SUN_IFACE_VERSION, "sun", XINE_VERSION_CODE, &ao_info_sun, ao_sun_init_class },
{ PLUGIN_NONE, 0, "", 0, NULL, NULL }
};