summaryrefslogtreecommitdiffstats
path: root/pcm
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2006-02-21 16:13:57 +0000
committerTakashi Iwai <tiwai@suse.de>2006-02-21 16:13:57 +0000
commit6890d16836e85deed9e8ca91d095473347013ccc (patch)
treebf5fa3bcb64af29d6264ff925f8e667e02bd16fc /pcm
parent6074e887419c70bed8a9177a4d78357156c7c611 (diff)
Structure reorganziation, added polyp plugin
- Reorganized the directory structure: Now each plugin(s) is loaded in own subdirectory. - Added polypaudio plugin by Pierre Ossman <ossman@cendio.se> - Fixed COPYING file to LGPL (under which all codes are released, so far)
Diffstat (limited to 'pcm')
-rw-r--r--pcm/Makefile.am2
-rw-r--r--pcm/jack/Makefile.am10
-rw-r--r--pcm/jack/README46
-rw-r--r--pcm/jack/pcm_jack.c428
-rw-r--r--pcm/oss/Makefile.am10
-rw-r--r--pcm/oss/README33
-rw-r--r--pcm/oss/pcm_oss.c423
7 files changed, 0 insertions, 952 deletions
diff --git a/pcm/Makefile.am b/pcm/Makefile.am
deleted file mode 100644
index 9f0dd9a..0000000
--- a/pcm/Makefile.am
+++ /dev/null
@@ -1,2 +0,0 @@
-SUBDIRS = oss jack
-
diff --git a/pcm/jack/Makefile.am b/pcm/jack/Makefile.am
deleted file mode 100644
index e71ce65..0000000
--- a/pcm/jack/Makefile.am
+++ /dev/null
@@ -1,10 +0,0 @@
-asound_module_pcm_jack_LTLIBRARIES = libasound_module_pcm_jack.la
-
-asound_module_pcm_jackdir = $(libdir)/alsa-lib
-
-AM_CFLAGS = -Wall -g @ALSA_CFLAGS@ @JACK_CFLAGS@
-libasound_module_pcm_jack_la_SOURCES = pcm_jack.c
-libasound_module_pcm_jack_la_LDFLAGS = -module -avoid-version -export-dynamic
-libasound_module_pcm_jack_la_LIBADD = @ALSA_LIBS@ @JACK_LIBS@
-
-EXTRA_DIST = README
diff --git a/pcm/jack/README b/pcm/jack/README
deleted file mode 100644
index 4579174..0000000
--- a/pcm/jack/README
+++ /dev/null
@@ -1,46 +0,0 @@
-JACK <--> ALSA PCM plugin
-=========================
-
-This plugin converts the ALSA API over JACK (Jack Audio Connection
-Kit, http://jackit.sf.net) API. ALSA native applications can work
-transparently together with jackd for both playback and capture.
-
- ALSA apps (playback) -> ALSA-lib -> JACK plugin -> JACK deamon
- ALSA apps (capture) <- ALSA-lib <- JACK plugin <- JACK daemon
-
-This plugin provides the PCM type "jack". The typical configuration
-looks like below:
-
- pcm.jack {
- type jack
- playback_ports {
- 0 alsa_pcm:playback_1
- 1 alsa_pcm:playback_1
- }
- capture_ports {
- 0 alsa_pcm:capture_1
- 1 alsa_pcm:pcapture_1
- }
- }
-
-Put the above to ~/.asoundrc (or /etc/asound.conf), and use "jack" PCM
-with your ALSA apps. For example,
-
- % aplay -Djack foo.wav
-
-The jack plugin can have two config options: playback_ports and
-capture_ports. Both are compound type config, including the following
-format:
- {
- channel port-name
- channel port-name
- ...
- }
-The first argument is the channel number (zero-based) and the second
-is the corresponding JACK port name.
-
-The plugin is installed in /usr/lib/alsa-lib directory as default,
-which is the default search path of additional plugins for alsa-lib.
-On a 64bit system like x86-64, the proper prefix option (typically,
---prefix=/usr/lib64) must be given to configure script.
-
diff --git a/pcm/jack/pcm_jack.c b/pcm/jack/pcm_jack.c
deleted file mode 100644
index 855f837..0000000
--- a/pcm/jack/pcm_jack.c
+++ /dev/null
@@ -1,428 +0,0 @@
-/*
- * PCM - JACK plugin
- *
- * Copyright (c) 2003 by Maarten de Boer <mdeboer@iua.upf.es>
- * 2005 Takashi Iwai <tiwai@suse.de>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <byteswap.h>
-#include <sys/shm.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <jack/jack.h>
-#include <alsa/asoundlib.h>
-#include <alsa/pcm_external.h>
-
-typedef enum _jack_format {
- SND_PCM_JACK_FORMAT_RAW
-} snd_pcm_jack_format_t;
-
-typedef struct {
- snd_pcm_ioplug_t io;
-
- int fd;
- int activated; /* jack is activated? */
-
- char **port_names;
- unsigned int num_ports;
- unsigned int hw_ptr;
- unsigned int sample_bits;
-
- unsigned int channels;
- snd_pcm_channel_area_t *areas;
-
- jack_port_t **ports;
- jack_client_t *client;
-} snd_pcm_jack_t;
-
-static void snd_pcm_jack_free(snd_pcm_jack_t *jack)
-{
- if (jack) {
- unsigned int i;
- if (jack->client)
- jack_client_close(jack->client);
- if (jack->port_names) {
- for (i = 0; i < jack->num_ports; i++)
- free(jack->port_names[i]);
- free(jack->port_names);
- }
- close(jack->fd);
- close(jack->io.poll_fd);
- free(jack->areas);
- free(jack);
- }
-}
-
-static int snd_pcm_jack_close(snd_pcm_ioplug_t *io)
-{
- snd_pcm_jack_t *jack = io->private_data;
- snd_pcm_jack_free(jack);
- return 0;
-}
-
-static int snd_pcm_jack_poll_revents(snd_pcm_ioplug_t *io,
- struct pollfd *pfds, unsigned int nfds,
- unsigned short *revents)
-{
- static char buf[1];
-
- assert(pfds && nfds == 1 && revents);
-
- read(pfds[0].fd, buf, 1);
-
- *revents = pfds[0].revents;
- return 0;
-}
-
-static snd_pcm_sframes_t snd_pcm_jack_pointer(snd_pcm_ioplug_t *io)
-{
- snd_pcm_jack_t *jack = io->private_data;
- return jack->hw_ptr;
-}
-
-static int
-snd_pcm_jack_process_cb(jack_nframes_t nframes, snd_pcm_ioplug_t *io)
-{
- snd_pcm_jack_t *jack = io->private_data;
- const snd_pcm_channel_area_t *areas;
- snd_pcm_uframes_t xfer = 0;
- static char buf[1];
- unsigned int channel;
-
- for (channel = 0; channel < io->channels; channel++) {
- jack->areas[channel].addr =
- jack_port_get_buffer (jack->ports[channel], nframes);
- jack->areas[channel].first = 0;
- jack->areas[channel].step = jack->sample_bits;
- }
-
- if (io->state != SND_PCM_STATE_RUNNING) {
- if (io->stream == SND_PCM_STREAM_PLAYBACK) {
- for (channel = 0; channel < io->channels; channel++)
- snd_pcm_area_silence(&jack->areas[channel], 0, nframes, io->format);
- return 0;
- }
- }
-
- areas = snd_pcm_ioplug_mmap_areas(io);
-
- while (xfer < nframes) {
- snd_pcm_uframes_t frames = nframes - xfer;
- snd_pcm_uframes_t offset = jack->hw_ptr;
- snd_pcm_uframes_t cont = io->buffer_size - offset;
-
- if (cont < frames)
- frames = cont;
-
- for (channel = 0; channel < io->channels; channel++) {
- if (io->stream == SND_PCM_STREAM_PLAYBACK)
- snd_pcm_area_copy(&jack->areas[channel], xfer, &areas[channel], offset, frames, io->format);
- else
- snd_pcm_area_copy(&areas[channel], offset, &jack->areas[channel], xfer, frames, io->format);
- }
-
- jack->hw_ptr += frames;
- jack->hw_ptr %= io->buffer_size;
- xfer += frames;
- }
-
- write(jack->fd, buf, 1); /* for polling */
-
- return 0;
-}
-
-static int snd_pcm_jack_prepare(snd_pcm_ioplug_t *io)
-{
- snd_pcm_jack_t *jack = io->private_data;
- unsigned int i;
-
- jack->hw_ptr = 0;
-
- if (jack->ports)
- return 0;
-
- jack->ports = calloc(io->channels, sizeof(jack_port_t*));
-
- for (i = 0; i < io->channels; i++) {
- char port_name[32];
- if (io->stream == SND_PCM_STREAM_PLAYBACK) {
-
- sprintf(port_name, "out_%03d\n", i);
- jack->ports[i] = jack_port_register(jack->client, port_name,
- JACK_DEFAULT_AUDIO_TYPE,
- JackPortIsOutput, 0);
- } else {
- sprintf(port_name, "in_%03d\n", i);
- jack->ports[i] = jack_port_register(jack->client, port_name,
- JACK_DEFAULT_AUDIO_TYPE,
- JackPortIsInput, 0);
- }
- }
-
- jack_set_process_callback(jack->client,
- (JackProcessCallback)snd_pcm_jack_process_cb, io);
- return 0;
-}
-
-static int snd_pcm_jack_start(snd_pcm_ioplug_t *io)
-{
- snd_pcm_jack_t *jack = io->private_data;
- unsigned int i;
-
- if (jack_activate (jack->client))
- return -EIO;
-
- jack->activated = 1;
-
- for (i = 0; i < io->channels && i < jack->num_ports; i++) {
- if (jack->port_names[i]) {
- const char *src, *dst;
- if (io->stream == SND_PCM_STREAM_PLAYBACK) {
- src = jack_port_name(jack->ports[i]);
- dst = jack->port_names[i];
- } else {
- src = jack->port_names[i];
- dst = jack_port_name(jack->ports[i]);
- }
- if (jack_connect(jack->client, src, dst)) {
- fprintf(stderr, "cannot connect %s to %s\n", src, dst);
- return -EIO;
- }
- }
- }
-
- return 0;
-}
-
-static int snd_pcm_jack_stop(snd_pcm_ioplug_t *io)
-{
- snd_pcm_jack_t *jack = io->private_data;
-
- if (jack->activated) {
- jack_deactivate(jack->client);
- jack->activated = 0;
- }
-#if 0
- unsigned i;
- for (i = 0; i < io->channels; i++) {
- if (jack->ports[i]) {
- jack_port_unregister(jack->client, jack->ports[i]);
- jack->ports[i] = NULL;
- }
- }
-#endif
- return 0;
-}
-
-static snd_pcm_ioplug_callback_t jack_pcm_callback = {
- .close = snd_pcm_jack_close,
- .start = snd_pcm_jack_start,
- .stop = snd_pcm_jack_stop,
- .pointer = snd_pcm_jack_pointer,
- .prepare = snd_pcm_jack_prepare,
- .poll_revents = snd_pcm_jack_poll_revents,
-};
-
-#define ARRAY_SIZE(ary) (sizeof(ary)/sizeof(ary[0]))
-
-static int jack_set_hw_constraint(snd_pcm_jack_t *jack)
-{
- unsigned int access_list[] = {
- SND_PCM_ACCESS_MMAP_INTERLEAVED,
- SND_PCM_ACCESS_MMAP_NONINTERLEAVED,
- SND_PCM_ACCESS_RW_INTERLEAVED,
- SND_PCM_ACCESS_RW_NONINTERLEAVED
- };
- unsigned int format = SND_PCM_FORMAT_FLOAT;
- unsigned int rate = jack_get_sample_rate(jack->client);
- int err;
-
- jack->sample_bits = snd_pcm_format_physical_width(format);
- if ((err = snd_pcm_ioplug_set_param_list(&jack->io, SND_PCM_IOPLUG_HW_ACCESS,
- ARRAY_SIZE(access_list), access_list)) < 0 ||
- (err = snd_pcm_ioplug_set_param_list(&jack->io, SND_PCM_IOPLUG_HW_FORMAT,
- 1, &format)) < 0 ||
- (err = snd_pcm_ioplug_set_param_minmax(&jack->io, SND_PCM_IOPLUG_HW_CHANNELS,
- jack->channels, jack->channels)) < 0 ||
- (err = snd_pcm_ioplug_set_param_minmax(&jack->io, SND_PCM_IOPLUG_HW_RATE,
- rate, rate)) < 0 ||
- (err = snd_pcm_ioplug_set_param_minmax(&jack->io, SND_PCM_IOPLUG_HW_PERIOD_BYTES,
- 128, 64*1024)) < 0 ||
- (err = snd_pcm_ioplug_set_param_minmax(&jack->io, SND_PCM_IOPLUG_HW_PERIODS,
- 2, 64)) < 0)
- return err;
-
- return 0;
-}
-
-static int parse_ports(snd_pcm_jack_t *jack, snd_config_t *conf)
-{
- snd_config_iterator_t i, next;
- char **ports = NULL;
- unsigned int cnt = 0;
- unsigned int channel;
-
- if (conf) {
- snd_config_for_each(i, next, conf) {
- snd_config_t *n = snd_config_iterator_entry(i);
- const char *id;
- if (snd_config_get_id(n, &id) < 0)
- continue;
- cnt++;
- }
- jack->port_names = ports = calloc(cnt, sizeof(char*));
- if (ports == NULL)
- return -ENOMEM;
- jack->num_ports = cnt;
- snd_config_for_each(i, next, conf) {
- snd_config_t *n = snd_config_iterator_entry(i);
- const char *id;
- const char *port;
-
- if (snd_config_get_id(n, &id) < 0)
- continue;
- channel = atoi(id);
- if (snd_config_get_string(n, &port) < 0)
- continue;
- ports[channel] = port ? strdup(port) : NULL;
- }
- }
- return 0;
-}
-
-static int snd_pcm_jack_open(snd_pcm_t **pcmp, const char *name,
- snd_config_t *playback_conf,
- snd_config_t *capture_conf,
- snd_pcm_stream_t stream, int mode)
-{
- snd_pcm_jack_t *jack;
- int err;
- int fd[2];
- static unsigned int num = 0;
- char jack_client_name[32];
-
- assert(pcmp);
- jack = calloc(1, sizeof(*jack));
- if (!jack)
- return -ENOMEM;
-
- err = parse_ports(jack, stream == SND_PCM_STREAM_PLAYBACK ?
- playback_conf : capture_conf);
- if (err) {
- snd_pcm_jack_free(jack);
- return err;
- }
-
- jack->channels = jack->num_ports;
- if (jack->channels == 0) {
- SNDERR("define the %s_ports section",
- stream == SND_PCM_STREAM_PLAYBACK ? "playback" : "capture");
- snd_pcm_jack_free(jack);
- return -EINVAL;
- }
-
- if (snprintf(jack_client_name, sizeof(jack_client_name), "alsa-jack.%s%s.%d.%d", name,
- stream == SND_PCM_STREAM_PLAYBACK ? "P" : "C", getpid(), num++)
- >= (int)sizeof(jack_client_name)) {
- fprintf(stderr, "%s: WARNING: JACK client name '%s' truncated to %d characters, might not be unique\n",
- __func__, jack_client_name, (int)strlen(jack_client_name));
- }
-
- jack->client = jack_client_new(jack_client_name);
-
- if (jack->client == 0) {
- snd_pcm_jack_free(jack);
- return -ENOENT;
- }
-
- jack->areas = calloc(jack->channels, sizeof(snd_pcm_channel_area_t));
- if (! jack->areas) {
- snd_pcm_jack_free(jack);
- return -ENOMEM;
- }
-
- socketpair(AF_LOCAL, SOCK_STREAM, 0, fd);
-
- jack->fd = fd[0];
-
- jack->io.version = SND_PCM_IOPLUG_VERSION;
- jack->io.name = "ALSA <-> JACK PCM I/O Plugin";
- jack->io.callback = &jack_pcm_callback;
- jack->io.private_data = jack;
- jack->io.poll_fd = fd[1];
- jack->io.poll_events = POLLIN;
- jack->io.mmap_rw = 1;
-
- err = snd_pcm_ioplug_create(&jack->io, name, stream, mode);
- if (err < 0) {
- snd_pcm_jack_free(jack);
- return err;
- }
-
- err = jack_set_hw_constraint(jack);
- if (err < 0) {
- snd_pcm_ioplug_delete(&jack->io);
- return err;
- }
-
- *pcmp = jack->io.pcm;
-
- return 0;
-}
-
-
-SND_PCM_PLUGIN_DEFINE_FUNC(jack)
-{
- snd_config_iterator_t i, next;
- snd_config_t *playback_conf = NULL;
- snd_config_t *capture_conf = NULL;
- int err;
-
- snd_config_for_each(i, next, conf) {
- snd_config_t *n = snd_config_iterator_entry(i);
- const char *id;
- if (snd_config_get_id(n, &id) < 0)
- continue;
- if (strcmp(id, "comment") == 0 || strcmp(id, "type") == 0)
- continue;
- if (strcmp(id, "playback_ports") == 0) {
- if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {
- SNDERR("Invalid type for %s", id);
- return -EINVAL;
- }
- playback_conf = n;
- continue;
- }
- if (strcmp(id, "capture_ports") == 0) {
- if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {
- SNDERR("Invalid type for %s", id);
- return -EINVAL;
- }
- capture_conf = n;
- continue;
- }
- SNDERR("Unknown field %s", id);
- return -EINVAL;
- }
-
- err = snd_pcm_jack_open(pcmp, name, playback_conf, capture_conf, stream, mode);
-
- return err;
-}
-
-SND_PCM_PLUGIN_SYMBOL(jack);
diff --git a/pcm/oss/Makefile.am b/pcm/oss/Makefile.am
deleted file mode 100644
index c907231..0000000
--- a/pcm/oss/Makefile.am
+++ /dev/null
@@ -1,10 +0,0 @@
-asound_module_pcm_oss_LTLIBRARIES = libasound_module_pcm_oss.la
-
-asound_module_pcm_ossdir = $(libdir)/alsa-lib
-
-AM_CFLAGS = -Wall -g @ALSA_CFLAGS@
-libasound_module_pcm_oss_la_SOURCES = pcm_oss.c
-libasound_module_pcm_oss_la_LDFLAGS = -module -avoid-version -export-dynamic
-libasound_module_pcm_oss_la_LIBADD = @ALSA_LIBS@
-
-EXTRA_DIST = README
diff --git a/pcm/oss/README b/pcm/oss/README
deleted file mode 100644
index 42b73cb..0000000
--- a/pcm/oss/README
+++ /dev/null
@@ -1,33 +0,0 @@
-OSS <--> ALSA PCM plugin
-========================
-
-This plugin converts the ALSA API over OSS API. With this plugin,
-ALSA native apps can run on OSS drivers.
-
-This plugin provides the PCM type "oss". The typical configuration
-looks like below:
-
- pcm.oss {
- type oss
- device /dev/dsp
- }
-
-Put the above to ~/.asoundrc (or /etc/asound.conf), and use "oss" PCM
-with your ALSA apps. For example,
-
- % aplay -Doss foo.wav
-
-For playing arbitrary formats, you should use "plug" layer together,
-
- % aplay -Dplug:oss foo.wav
-
-The oss plugin can have an option: device. This specifies the device
-file path of OSS to open. If not given, /dev/dsp is used.
-
-The function supported by this plugin is limited. For example, you
-cannot use dmix together with this plugin. Don't expect too much :)
-
-The plugin is installed in /usr/lib/alsa-lib directory as default,
-which is the default search path of additional plugins for alsa-lib.
-On a 64bit system like x86-64, the proper prefix option (typically,
---prefix=/usr/lib64) must be given to configure script.
diff --git a/pcm/oss/pcm_oss.c b/pcm/oss/pcm_oss.c
deleted file mode 100644
index fb520f8..0000000
--- a/pcm/oss/pcm_oss.c
+++ /dev/null
@@ -1,423 +0,0 @@
-/*
- * ALSA <-> OSS PCM I/O plugin
- *
- * Copyright (c) 2005 by Takashi Iwai <tiwai@suse.de>
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <stdio.h>
-#include <sys/ioctl.h>
-#include <alsa/asoundlib.h>
-#include <alsa/pcm_external.h>
-#include <linux/soundcard.h>
-
-typedef struct snd_pcm_oss {
- snd_pcm_ioplug_t io;
- char *device;
- int fd;
- int fragment_set;
- int caps;
- int format;
- unsigned int period_shift;
- unsigned int periods;
- unsigned int frame_bytes;
-} snd_pcm_oss_t;
-
-static snd_pcm_sframes_t oss_write(snd_pcm_ioplug_t *io,
- const snd_pcm_channel_area_t *areas,
- snd_pcm_uframes_t offset,
- snd_pcm_uframes_t size)
-{
- snd_pcm_oss_t *oss = io->private_data;
- const char *buf;
- ssize_t result;
-
- /* we handle only an interleaved buffer */
- buf = (char *)areas->addr + (areas->first + areas->step * offset) / 8;
- size *= oss->frame_bytes;
- result = write(oss->fd, buf, size);
- if (result <= 0)
- return result;
- return result / oss->frame_bytes;
-}
-
-static snd_pcm_sframes_t oss_read(snd_pcm_ioplug_t *io,
- const snd_pcm_channel_area_t *areas,
- snd_pcm_uframes_t offset,
- snd_pcm_uframes_t size)
-{
- snd_pcm_oss_t *oss = io->private_data;
- char *buf;
- ssize_t result;
-
- /* we handle only an interleaved buffer */
- buf = (char *)areas->addr + (areas->first + areas->step * offset) / 8;
- size *= oss->frame_bytes;
- result = read(oss->fd, buf, size);
- if (result <= 0)
- return result;
- return result / oss->frame_bytes;
-}
-
-static snd_pcm_sframes_t oss_pointer(snd_pcm_ioplug_t *io)
-{
- snd_pcm_oss_t *oss = io->private_data;
- struct count_info info;
- int ptr;
-
- if (ioctl(oss->fd, io->stream == SND_PCM_STREAM_PLAYBACK ?
- SNDCTL_DSP_GETOPTR : SNDCTL_DSP_GETIPTR, &info) < 0) {
- fprintf(stderr, "*** OSS: oss_pointer error\n");
- return 0;
- }
- ptr = snd_pcm_bytes_to_frames(io->pcm, info.ptr);
- return ptr;
-}
-
-static int oss_start(snd_pcm_ioplug_t *io)
-{
- snd_pcm_oss_t *oss = io->private_data;
- int tmp = io->stream == SND_PCM_STREAM_PLAYBACK ?
- PCM_ENABLE_OUTPUT : PCM_ENABLE_INPUT;
-
- if (ioctl(oss->fd, SNDCTL_DSP_SETTRIGGER, &tmp) < 0) {
- fprintf(stderr, "*** OSS: trigger failed\n");
- if (io->stream == SND_PCM_STREAM_CAPTURE)
- /* fake read to trigger */
- read(oss->fd, &tmp, 0);
- }
- return 0;
-}
-
-static int oss_stop(snd_pcm_ioplug_t *io)
-{
- snd_pcm_oss_t *oss = io->private_data;
- int tmp = 0;
-
- ioctl(oss->fd, SNDCTL_DSP_SETTRIGGER, &tmp);
- return 0;
-}
-
-static int oss_drain(snd_pcm_ioplug_t *io)
-{
- snd_pcm_oss_t *oss = io->private_data;
-
- if (io->stream == SND_PCM_STREAM_PLAYBACK)
- ioctl(oss->fd, SNDCTL_DSP_SYNC);
- return 0;
-}
-
-static int oss_prepare(snd_pcm_ioplug_t *io)
-{
- snd_pcm_oss_t *oss = io->private_data;
- int tmp;
-
- ioctl(oss->fd, SNDCTL_DSP_RESET);
-
- tmp = io->channels;
- if (ioctl(oss->fd, SNDCTL_DSP_CHANNELS, &tmp) < 0) {
- perror("SNDCTL_DSP_CHANNELS");
- return -EINVAL;
- }
- tmp = oss->format;
- if (ioctl(oss->fd, SNDCTL_DSP_SETFMT, &tmp) < 0) {
- perror("SNDCTL_DSP_SETFMT");
- return -EINVAL;
- }
- tmp = io->rate;
- if (ioctl(oss->fd, SNDCTL_DSP_SPEED, &tmp) < 0 ||
- tmp > io->rate * 1.01 || tmp < io->rate * 0.99) {
- perror("SNDCTL_DSP_SPEED");
- return -EINVAL;
- }
- return 0;
-}
-
-static int oss_hw_params(snd_pcm_ioplug_t *io, snd_pcm_hw_params_t *params)
-{
- snd_pcm_oss_t *oss = io->private_data;
- int i, tmp, err;
- unsigned int period_bytes;
- long oflags, flags;
-
- oss->frame_bytes = (snd_pcm_format_physical_width(io->format) * io->channels) / 8;
- switch (io->format) {
- case SND_PCM_FORMAT_U8:
- oss->format = AFMT_U8;
- break;
- case SND_PCM_FORMAT_S16_LE:
- oss->format = AFMT_S16_LE;
- break;
- case SND_PCM_FORMAT_S16_BE:
- oss->format = AFMT_S16_BE;
- break;
- default:
- fprintf(stderr, "*** OSS: unsupported format %s\n", snd_pcm_format_name(io->format));
- return -EINVAL;
- }
- period_bytes = io->period_size * oss->frame_bytes;
- oss->period_shift = 0;
- for (i = 31; i >= 4; i--) {
- if (period_bytes & (1U << i)) {
- oss->period_shift = i;
- break;
- }
- }
- if (! oss->period_shift) {
- fprintf(stderr, "*** OSS: invalid period size %d\n", (int)io->period_size);
- return -EINVAL;
- }
-
- _retry:
- tmp = oss->period_shift | (oss->periods << 16);
- if (ioctl(oss->fd, SNDCTL_DSP_SETFRAGMENT, &tmp) < 0) {
- if (! oss->fragment_set) {
- perror("SNDCTL_DSP_SETFRAGMENT");
- fprintf(stderr, "*** period shift = %d, periods = %d\n", oss->period_shift, oss->periods);
- return -EINVAL;
- }
- /* OSS has no proper way to reinitialize the fragments */
- /* try to reopen the device */
- close(oss->fd);
- oss->fd = open(oss->device, io->stream == SND_PCM_STREAM_PLAYBACK ?
- O_WRONLY : O_RDONLY);
- if (oss->fd < 0) {
- err = -errno;
- SNDERR("Cannot reopen the device %s", oss->device);
- return err;
- }
- io->poll_fd = oss->fd;
- io->poll_events = io->stream == SND_PCM_STREAM_PLAYBACK ?
- POLLOUT : POLLIN;
- snd_pcm_ioplug_reinit_status(io);
- oss->fragment_set = 0;
- goto _retry;
- }
- oss->fragment_set = 1;
-
- if ((flags = fcntl(oss->fd, F_GETFL)) < 0) {
- err = -errno;
- perror("F_GETFL");
- } else {
- oflags = flags;
- if (io->nonblock)
- flags |= O_NONBLOCK;
- else
- flags &= ~O_NONBLOCK;
- if (flags != oflags &&
- fcntl(oss->fd, F_SETFL, flags) < 0) {
- err = -errno;
- perror("F_SETFL");
- }
- }
-
- return 0;
-}
-
-#define ARRAY_SIZE(ary) (sizeof(ary)/sizeof(ary[0]))
-
-static int oss_hw_constraint(snd_pcm_oss_t *oss)
-{
- snd_pcm_ioplug_t *io = &oss->io;
- static snd_pcm_access_t access_list[] = {
- SND_PCM_ACCESS_RW_INTERLEAVED,
- SND_PCM_ACCESS_MMAP_INTERLEAVED
- };
- unsigned int nformats;
- unsigned int format[5];
- unsigned int nchannels;
- unsigned int channel[6];
- /* period and buffer bytes must be power of two */
- static unsigned int bytes_list[] = {
- 1U<<8, 1U<<9, 1U<<10, 1U<<11, 1U<<12, 1U<<13, 1U<<14, 1U<<15,
- 1U<<16, 1U<<17, 1U<<18, 1U<<19, 1U<<20, 1U<<21, 1U<<22, 1U<<23
- };
- int i, err, tmp;
-
- /* check trigger */
- oss->caps = 0;
- if (ioctl(oss->fd, SNDCTL_DSP_GETCAPS, &oss->caps) >= 0) {
- if (! (oss->caps & DSP_CAP_TRIGGER))
- fprintf(stderr, "*** OSS: trigger is not supported!\n");
- }
-
- /* access type - interleaved only */
- if ((err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS,
- ARRAY_SIZE(access_list), access_list)) < 0)
- return err;
-
- /* supported formats */
- tmp = 0;
- ioctl(oss->fd, SNDCTL_DSP_GETFMTS, &tmp);
- nformats = 0;
- if (tmp & AFMT_U8)
- format[nformats++] = SND_PCM_FORMAT_U8;
- if (tmp & AFMT_S16_LE)
- format[nformats++] = SND_PCM_FORMAT_S16_LE;
- if (tmp & AFMT_S16_BE)
- format[nformats++] = SND_PCM_FORMAT_S16_BE;
- if (tmp & AFMT_MU_LAW)
- format[nformats++] = SND_PCM_FORMAT_MU_LAW;
- if (! nformats)
- format[nformats++] = SND_PCM_FORMAT_S16;
- if ((err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_FORMAT,
- nformats, format)) < 0)
- return err;
-
- /* supported channels */
- nchannels = 0;
- for (i = 0; i < 6; i++) {
- tmp = i + 1;
- if (ioctl(oss->fd, SNDCTL_DSP_CHANNELS, &tmp) >= 0)
- channel[nchannels++] = tmp;
- }
- if (! nchannels) /* assume 2ch stereo */
- err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_CHANNELS,
- 2, 2);
- else
- err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_CHANNELS,
- nchannels, channel);
- if (err < 0)
- return err;
-
- /* supported rates */
- /* FIXME: should query? */
- err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_RATE, 8000, 480000);
- if (err < 0)
- return err;
-
- /* period size (in power of two) */
- err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_PERIOD_BYTES,
- ARRAY_SIZE(bytes_list), bytes_list);
- if (err < 0)
- return err;
- /* periods */
- err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIODS, 2, 1024);
- if (err < 0)
- return err;
- /* buffer size (in power of two) */
- err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_BUFFER_BYTES,
- ARRAY_SIZE(bytes_list), bytes_list);
- if (err < 0)
- return err;
-
- return 0;
-}
-
-
-static int oss_close(snd_pcm_ioplug_t *io)
-{
- snd_pcm_oss_t *oss = io->private_data;
-
- close(oss->fd);
- free(oss->device);
- free(oss);
- return 0;
-}
-
-static snd_pcm_ioplug_callback_t oss_playback_callback = {
- .start = oss_start,
- .stop = oss_stop,
- .transfer = oss_write,
- .pointer = oss_pointer,
- .close = oss_close,
- .hw_params = oss_hw_params,
- .prepare = oss_prepare,
- .drain = oss_drain,
-};
-
-static snd_pcm_ioplug_callback_t oss_capture_callback = {
- .start = oss_start,
- .stop = oss_stop,
- .transfer = oss_read,
- .pointer = oss_pointer,
- .close = oss_close,
- .hw_params = oss_hw_params,
- .prepare = oss_prepare,
- .drain = oss_drain,
-};
-
-
-SND_PCM_PLUGIN_DEFINE_FUNC(oss)
-{
- snd_config_iterator_t i, next;
- const char *device = "/dev/dsp";
- int err;
- snd_pcm_oss_t *oss;
-
- snd_config_for_each(i, next, conf) {
- snd_config_t *n = snd_config_iterator_entry(i);
- const char *id;
- if (snd_config_get_id(n, &id) < 0)
- continue;
- if (strcmp(id, "comment") == 0 || strcmp(id, "type") == 0)
- continue;
- if (strcmp(id, "device") == 0) {
- if (snd_config_get_string(n, &device) < 0) {
- SNDERR("Invalid type for %s", id);
- return -EINVAL;
- }
- continue;
- }
- SNDERR("Unknown field %s", id);
- return -EINVAL;
- }
-
- oss = calloc(1, sizeof(*oss));
- oss->device = strdup(device);
- if (oss->device == NULL) {
- SNDERR("cannot allocate");
- free(oss);
- return -ENOMEM;
- }
- oss->fd = open(device, stream == SND_PCM_STREAM_PLAYBACK ?
- O_WRONLY : O_RDONLY);
- if (oss->fd < 0) {
- err = -errno;
- SNDERR("Cannot open device %s", device);
- goto error;
- }
-
- oss->io.version = SND_PCM_IOPLUG_VERSION;
- oss->io.name = "ALSA <-> OSS PCM I/O Plugin";
- oss->io.poll_fd = oss->fd;
- oss->io.poll_events = stream == SND_PCM_STREAM_PLAYBACK ? POLLOUT : POLLIN;
- oss->io.mmap_rw = 0;
- oss->io.callback = stream == SND_PCM_STREAM_PLAYBACK ?
- &oss_playback_callback : &oss_capture_callback;
- oss->io.private_data = oss;
-
- err = snd_pcm_ioplug_create(&oss->io, name, stream, mode);
- if (err < 0)
- goto error;
-
- if ((err = oss_hw_constraint(oss)) < 0) {
- snd_pcm_ioplug_delete(&oss->io);
- return err;
- }
-
- *pcmp = oss->io.pcm;
- return 0;
-
- error:
- if (oss->fd >= 0)
- close(oss->fd);
- free(oss->device);
- free(oss);
- return err;
-}
-
-SND_PCM_PLUGIN_SYMBOL(oss);