aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/sfx/pcm_device/alsa.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/sfx/pcm_device/alsa.cpp')
-rw-r--r--engines/sci/sfx/pcm_device/alsa.cpp375
1 files changed, 0 insertions, 375 deletions
diff --git a/engines/sci/sfx/pcm_device/alsa.cpp b/engines/sci/sfx/pcm_device/alsa.cpp
deleted file mode 100644
index 4698d66478..0000000000
--- a/engines/sci/sfx/pcm_device/alsa.cpp
+++ /dev/null
@@ -1,375 +0,0 @@
-/***************************************************************************
- alsa.c Copyright (C) 2004 Walter van Niftrik
-
-
- This program may be modified and copied freely according to the terms of
- the GNU general public license (GPL), as long as the above copyright
- notice and the licensing information contained herein are preserved.
-
- Please refer to www.gnu.org for licensing details.
-
- This work is provided AS IS, without warranty of any kind, expressed or
- implied, including but not limited to the warranties of merchantibility,
- noninfringement, and fitness for a specific purpose. The author will not
- be held liable for any damage caused by this work or derivatives of it.
-
- By using this source code, you agree to the licensing terms as stated
- above.
-
-
- Please contact the maintainer for bug reports or inquiries.
-
- Current Maintainer:
-
- Walter van Niftrik <w.f.b.w.v.niftrik@stud.tue.nl>
-
-***************************************************************************/
-
-/* Based on ALSA's pcm.c example. */
-
-#include <sfx_pcm.h>
-#include "audiobuf.h"
-
-#ifdef HAVE_ALSA
-#ifdef HAVE_PTHREAD
-
-#define ALSA_PCM_NEW_HW_PARAMS_API
-#define ALSA_PCM_NEW_SW_PARAMS_API
-
-#include <alsa/asoundlib.h>
-#include <pthread.h>
-
-static const char *device = "default"; /* FIXME */
-static snd_pcm_format_t format = SND_PCM_FORMAT_S16;
-static unsigned int rate = 44100; /* FIXME */
-static unsigned int channels = 2; /* FIXME */
-static unsigned int buffer_time = 100000; /* FIXME */
-static unsigned int period_time = 1000000 / 60; /* 60Hz */ /* FIXME */
-
-static snd_pcm_sframes_t buffer_size;
-static snd_pcm_sframes_t period_size;
-
-static int frame_size;
-static long last_callback_secs, last_callback_usecs;
-
-static sfx_audio_buf_t audio_buffer;
-static void (*alsa_sfx_timer_callback)(void *data);
-static void *alsa_sfx_timer_data;
-
-static snd_pcm_t *handle;
-
-static pthread_t thread;
-static volatile byte run_thread;
-
-static pthread_mutex_t mutex;
-
-static int
-xrun_recovery(snd_pcm_t *handle, int err) {
- if (err == -EPIPE) { /* under-run */
- err = snd_pcm_prepare(handle);
- if (err < 0)
- fprintf(stderr, "Can't recovery from underrun, prepare failed: %s\n", snd_strerror(err));
- return 0;
- } else if (err == -ESTRPIPE) {
- while ((err = snd_pcm_resume(handle)) == -EAGAIN)
- sleep(1); /* wait until the suspend flag is released */
- if (err < 0) {
- err = snd_pcm_prepare(handle);
- if (err < 0)
- fprintf(stderr, "Can't recovery from suspend, prepare failed: %s\n", snd_strerror(err));
- }
- return 0;
- }
- return err;
-}
-
-static void *
-alsa_thread(void *arg) {
- gint16 *ptr;
- int err, cptr;
- guint8 *buf;
- sfx_pcm_device_t *self = (sfx_pcm_device_t *) arg;
-
- buf = (guint8 *) malloc(period_size * frame_size);
-
- while (run_thread) {
- ptr = (gint16 *) buf;
- cptr = period_size;
-
- sci_gettime(&last_callback_secs, &last_callback_usecs);
-
- self->timer->block();
-
- if (alsa_sfx_timer_callback)
- alsa_sfx_timer_callback(alsa_sfx_timer_data);
-
- self->timer->unblock();
-
- sfx_audbuf_read(&audio_buffer, buf, period_size);
-
- while (cptr > 0) {
- err = snd_pcm_writei(handle, ptr, cptr);
- if (err == -EAGAIN)
- continue;
- if (err < 0) {
- if (xrun_recovery(handle, err) < 0) {
- fprintf(stderr, "[SND:ALSA] Write error: %s\n", snd_strerror(err));
- run_thread = 0;
- }
- break; /* skip one period */
- }
- ptr += err * channels;
- cptr -= err;
- }
- }
-
- free(buf);
- return NULL;
-}
-
-static sfx_timestamp_t
-pcmout_alsa_output_timestamp(sfx_pcm_device_t *self) {
- /* Number of frames enqueued in the output device: */
- int delta = (buffer_size - period_size) / frame_size
- /* Number of frames enqueued in the internal audio buffer: */
- + audio_buffer.frames_nr;
-
- return sfx_timestamp_add(sfx_new_timestamp(last_callback_secs,
- last_callback_usecs,
- rate),
- delta);
-}
-
-static int
-pcmout_alsa_init(sfx_pcm_device_t *self) {
- unsigned int rrate;
- int err, dir;
- snd_pcm_hw_params_t *hwparams;
- snd_pcm_sw_params_t *swparams;
- pthread_attr_t attr;
-
- snd_pcm_hw_params_alloca(&hwparams);
- snd_pcm_sw_params_alloca(&swparams);
-
- err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0);
- if (err < 0) {
- sciprintf("[SND:ALSA] Playback open error: %s\n", snd_strerror(err));
- return SFX_ERROR;
- }
- err = snd_pcm_hw_params_any(handle, hwparams);
- if (err < 0) {
- sciprintf("[SND:ALSA] Broken configuration for playback: no configurations available: %s\n", snd_strerror(err));
- return SFX_ERROR;
- }
- err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
- if (err < 0) {
- sciprintf("[SND:ALSA] Access type not available for playback: %s\n", snd_strerror(err));
- return SFX_ERROR;
- }
- err = snd_pcm_hw_params_set_format(handle, hwparams, format);
- if (err < 0) {
- sciprintf("[SND:ALSA] Sample format not available for playback: %s\n", snd_strerror(err));
- return SFX_ERROR;
- }
- err = snd_pcm_hw_params_set_channels(handle, hwparams, channels);
- if (err < 0) {
- sciprintf("[SND:ALSA] Channels count (%i) not available for playback: %s\n", channels, snd_strerror(err));
- return SFX_ERROR;
- }
- rrate = rate;
- err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &rrate, 0);
- if (err < 0) {
- sciprintf("[SND:ALSA] Rate %iHz not available for playback: %s\n", rate, snd_strerror(err));
- return SFX_ERROR;
- }
- if (rrate != rate) {
- sciprintf("[SND:ALSA] Rate doesn't match (requested %iHz, get %iHz)\n", rate, err);
- return SFX_ERROR;
- }
- err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, &dir);
- if (err < 0) {
- sciprintf("[SND:ALSA] Unable to set buffer time %i for playback: %s\n", buffer_time, snd_strerror(err));
- return SFX_ERROR;
- }
- err = snd_pcm_hw_params_get_buffer_size(hwparams, (snd_pcm_uframes_t*) & buffer_size);
- if (err < 0) {
- sciprintf("[SND:ALSA] Unable to get buffer size for playback: %s\n", snd_strerror(err));
- return SFX_ERROR;
- }
- err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, &dir);
- if (err < 0) {
- sciprintf("[SND:ALSA] Unable to set period time %i for playback: %s\n", period_time, snd_strerror(err));
- return SFX_ERROR;
- }
- err = snd_pcm_hw_params_get_period_size(hwparams, (snd_pcm_uframes_t*) & period_size, &dir);
- if (err < 0) {
- sciprintf("[SND:ALSA] Unable to get period size for playback: %s\n", snd_strerror(err));
- return SFX_ERROR;
- }
- if (period_size >= buffer_size) {
- sciprintf("[SND:ALSA] Period size %i matches or exceeds buffer size %i\n", period_size, buffer_size);
- return SFX_ERROR;
- }
- err = snd_pcm_hw_params(handle, hwparams);
- if (err < 0) {
- sciprintf("[SND:ALSA] Unable to set hw params for playback: %s\n", snd_strerror(err));
- return SFX_ERROR;
- }
- err = snd_pcm_sw_params_current(handle, swparams);
- if (err < 0) {
- sciprintf("[SND:ALSA] Unable to determine current swparams for playback: %s\n", snd_strerror(err));
- return SFX_ERROR;
- }
- err = snd_pcm_sw_params_set_start_threshold(handle, swparams, buffer_size);
- if (err < 0) {
- sciprintf("[SND:ALSA] Unable to set start threshold mode for playback: %s\n", snd_strerror(err));
- return SFX_ERROR;
- }
- err = snd_pcm_sw_params_set_avail_min(handle, swparams, period_size);
- if (err < 0) {
- sciprintf("[SND:ALSA] Unable to set avail min for playback: %s\n", snd_strerror(err));
- return SFX_ERROR;
- }
- err = snd_pcm_sw_params_set_xfer_align(handle, swparams, 1);
- if (err < 0) {
- sciprintf("[SND:ALSA] Unable to set transfer align for playback: %s\n", snd_strerror(err));
- return SFX_ERROR;
- }
- err = snd_pcm_sw_params(handle, swparams);
- if (err < 0) {
- sciprintf("[SND:ALSA] Unable to set sw params for playback: %s\n", snd_strerror(err));
- return SFX_ERROR;
- }
-
- self->buf_size = buffer_size;
- self->conf.rate = rate;
- self->conf.stereo = channels > 1;
- self->conf.format = SFX_PCM_FORMAT_S16_NATIVE;
-
- frame_size = SFX_PCM_FRAME_SIZE(self->conf);
-
- sfx_audbuf_init(&audio_buffer, self->conf);
-
- if (pthread_mutex_init(&mutex, NULL) != 0) {
- sciprintf("[SND:ALSA] Failed to create mutex\n");
- return SFX_ERROR;
- }
-
- run_thread = 1;
- if (pthread_create(&thread, NULL, alsa_thread, self) != 0) {
- sciprintf("[SND:ALSA] Failed to create thread\n");
- return SFX_ERROR;
- }
-
- return SFX_OK;
-}
-
-static int
-pcmout_alsa_output(sfx_pcm_device_t *self, byte *buf,
- int count, sfx_timestamp_t *ts) {
- if (ts)
- sfx_audbuf_write_timestamp(&audio_buffer, *ts);
-
- sfx_audbuf_write(&audio_buffer, buf, count);
- return SFX_OK;
-}
-
-static int
-pcmout_alsa_set_option(sfx_pcm_device_t *self, char *name, char *value) {
- return SFX_ERROR;
-}
-
-static void
-pcmout_alsa_exit(sfx_pcm_device_t *self) {
- int err;
-
- run_thread = 0;
- sciprintf("[SND:ALSA] Waiting for PCM thread to exit... ");
- if (!pthread_join(thread, NULL))
- sciprintf("OK\n");
- else
- sciprintf("Failed\n");
-
- pthread_mutex_destroy(&mutex);
-
- if ((err = snd_pcm_drop(handle)) < 0) {
- sciprintf("[SND:ALSA] Can't stop PCM device: %s\n", snd_strerror(err));
- }
- if ((err = snd_pcm_close(handle)) < 0) {
- sciprintf("[SND:ALSA] Can't close PCM device: %s\n", snd_strerror(err));
- }
-
- sfx_audbuf_free(&audio_buffer);
-}
-
-static int
-timer_alsa_set_option(char *name, char *value) {
- return SFX_ERROR;
-}
-
-
-static int
-timer_alsa_init(void (*callback)(void *data), void *data) {
- alsa_sfx_timer_callback = callback;
- alsa_sfx_timer_data = data;
-
- return SFX_OK;
-}
-
-static int
-timer_alsa_stop(void) {
- alsa_sfx_timer_callback = NULL;
-
- return SFX_OK;
-}
-
-static int
-timer_alsa_block(void) {
- if (pthread_mutex_lock(&mutex) != 0) {
- fprintf(stderr, "[SND:ALSA] Failed to lock mutex\n");
- return SFX_ERROR;
- }
-
- return SFX_OK;
-}
-
-static int
-timer_alsa_unblock(void) {
- if (pthread_mutex_unlock(&mutex) != 0) {
- fprintf(stderr, "[SND:ALSA] Failed to unlock mutex\n");
- return SFX_ERROR;
- }
-
- return SFX_OK;
-}
-
-#define ALSA_PCM_VERSION "0.2"
-
-sfx_timer_t pcmout_alsa_timer = {
- "alsa-pcm-timer",
- ALSA_PCM_VERSION,
- 0,
- 0,
- timer_alsa_set_option,
- timer_alsa_init,
- timer_alsa_stop,
- timer_alsa_block,
- timer_alsa_unblock
-};
-
-sfx_pcm_device_t sfx_pcm_driver_alsa = {
- "alsa",
- ALSA_PCM_VERSION,
- pcmout_alsa_init,
- pcmout_alsa_exit,
- pcmout_alsa_set_option,
- pcmout_alsa_output,
- pcmout_alsa_output_timestamp,
- {0, 0, 0},
- 0,
- &pcmout_alsa_timer,
- NULL
-};
-
-#endif /* HAVE_PTHREAD */
-#endif /* HAVE_ALSA */