summaryrefslogtreecommitdiff
path: root/src/audioio.cc
diff options
context:
space:
mode:
authorBent Bisballe Nyeng <deva@aasimon.org>2014-09-25 17:08:44 +0200
committerBent Bisballe Nyeng <deva@aasimon.org>2014-09-25 17:08:44 +0200
commit4f6b15ea26b5fa09f300f67e4ce1057c2b39a3aa (patch)
tree45d7bb4a9a90ef603b5a7a65a4d4d4309a7a1538 /src/audioio.cc
parent0602763044f0f0f9163f2a888627213347d3dbb7 (diff)
New API, new name, new version.
Diffstat (limited to 'src/audioio.cc')
-rw-r--r--src/audioio.cc287
1 files changed, 287 insertions, 0 deletions
diff --git a/src/audioio.cc b/src/audioio.cc
new file mode 100644
index 0000000..bb04762
--- /dev/null
+++ b/src/audioio.cc
@@ -0,0 +1,287 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * audioio.cc
+ *
+ * Thu Sep 25 15:55:14 CEST 2014
+ * Copyright 2014 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of LibAudioIO.
+ *
+ * LibAudioIO 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.
+ *
+ * LibAudioIO 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 LibAudioIO; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "audioio.h"
+
+#include "device.h"
+#include "mixer.h"
+#include "source.h"
+#include "sink.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+#define NO_ERROR 0
+
+#define OUT_OF_MEMORY -101
+#define MISSING_HANDLE -102
+
+#define COULD_NOT_OPEN_DEVICE -203
+#define COULD_NOT_SET_HW_PARAMS -204
+#define COULD_NOT_INIT_PARAMS -205
+#define COULD_NOT_SET_ACCESS_MODE -206
+#define COULD_NOT_SET_FORMAT -207
+#define COULD_NOT_SET_CHANNELS -208
+#define COULD_NOT_SET_SAMPLE_RATE -209
+#define COULD_NOT_SET_PERIOD_SIZE -210
+
+#define BUFFER_TOO_SMALL -305
+#define BUFFER_OVERRUN -306
+#define READ_ERROR -307
+#define SHORT_READ -308
+
+#define MIXER_INIT_FAILED -400
+
+#define MIXER_NOT_INITIALISED -401
+#define INVALID_MIXER_LEVEL -402
+#define INVALID_CHANNEL_NUMBER -403
+#define COULD_NOT_SET_MIXER_LEVEL -404
+*/
+
+#define MAGIC 0xdeadbeef
+
+struct aio_t {
+ unsigned int magic;
+
+ Device *device;
+
+ Source *source;
+ Mixer *source_mixer;
+
+ Sink *sink;
+ Mixer *sink_mixer;
+};
+
+// Check if 'h' is a valid aio_t handle and report/return error if not.
+#define CHECK_HANDLE(h) \
+ do { \
+ if(!h || h->magic != MAGIC) { \
+ return MISSING_HANDLE; \
+ } \
+ } while(0)
+
+struct aio_t *aio_init(int *err,
+ const char *playback_device,
+ const char *playback_mixer,
+ const char *capture_device,
+ const char *capture_mixer,
+ unsigned int samplerate,
+ unsigned int channels)
+{
+ *err = NO_ERROR;
+
+ const char *device = playback_device;
+ if(device == NULL || strlen(device) == 0) device = capture_device;
+ if(device == NULL || strlen(device) == 0) {
+ *err = COULD_NOT_OPEN_DEVICE;
+ return NULL;
+ }
+
+ struct aio_t *h = new aio_t;
+ memset(h, 0, sizeof(struct aio_t));
+ h->magic = MAGIC;
+
+
+ if(h == NULL) {
+ *err = OUT_OF_MEMORY;
+ return NULL;
+ }
+
+ h->device = new Device(device);
+
+ if(playback_device != NULL && strlen(playback_device) > 0) {
+ h->sink = h->device->getSink(playback_device, samplerate, channels);
+ if(h->sink == NULL) {
+ *err = COULD_NOT_OPEN_DEVICE;
+ }
+ }
+
+ if(playback_mixer != NULL && strlen(playback_mixer) > 0) {
+ h->sink_mixer = h->device->getMixer(playback_mixer);
+ if(h->sink_mixer == NULL) {
+ *err = MIXER_INIT_FAILED;
+ }
+ }
+
+ if(capture_device != NULL && strlen(capture_device) > 0) {
+ h->source = h->device->getSource(capture_device, samplerate, channels);
+ if(h->sink == NULL) {
+ *err = COULD_NOT_OPEN_DEVICE;
+ }
+ }
+
+ if(capture_mixer != NULL && strlen(capture_mixer) > 0) {
+ h->source_mixer = h->device->getMixer(capture_mixer);
+ if(h->source_mixer == NULL) {
+ *err = MIXER_INIT_FAILED;
+ }
+ }
+
+ if(*err != NO_ERROR) {
+ h->magic = 0;
+ if(h->source) delete h->source;
+ if(h->source_mixer) delete h->source_mixer;
+ if(h->sink) delete h->sink;
+ if(h->sink_mixer) delete h->sink_mixer;
+ delete h;
+ return NULL;
+ }
+
+ return h;
+}
+
+int aio_read(struct aio_t *h, char *pcm, unsigned int maxsize)
+{
+ CHECK_HANDLE(h);
+
+ if(h->source) {
+ return h->source->readSamples(pcm, maxsize);
+ }
+
+ return MISSING_HANDLE;
+}
+
+int aio_write(struct aio_t *h, const char *pcm, unsigned int size)
+{
+ CHECK_HANDLE(h);
+
+ if(h->sink) {
+ return h->sink->writeSamples(pcm, size);
+ }
+
+ return MISSING_HANDLE;
+}
+
+int aio_set_playback_mixer_level(struct aio_t *h, unsigned int c, float level)
+{
+ CHECK_HANDLE(h);
+
+ if(h->sink_mixer) {
+ h->sink_mixer->setLevel(c, level);
+ return 0;
+ }
+
+ return MISSING_HANDLE;
+}
+
+int aio_get_playback_mixer_level(struct aio_t *h, unsigned int c, float *level)
+{
+ CHECK_HANDLE(h);
+
+ if(h->sink_mixer) {
+ float l = h->sink_mixer->level(c);
+ if(l < -1000) return INVALID_MIXER_LEVEL;
+ *level = l;
+ return 0;
+ }
+
+ return MISSING_HANDLE;
+}
+
+int aio_get_playback_mixer_level_range(struct aio_t *h, float *min, float *max)
+{
+ CHECK_HANDLE(h);
+
+ if(h->sink_mixer) {
+ Mixer::range_t r = h->sink_mixer->range();
+ *min = r.min;
+ *max = r.max;
+ return 0;
+ }
+
+ return MISSING_HANDLE;
+}
+
+int aio_set_capture_mixer_level(struct aio_t *h, unsigned int c, float level)
+{
+ CHECK_HANDLE(h);
+
+ if(h->source_mixer) {
+ h->source_mixer->setLevel(c, level);
+ return 0;
+ }
+
+ return MISSING_HANDLE;
+}
+
+int aio_get_capture_mixer_level(struct aio_t *h, unsigned int c, float *level)
+{
+ CHECK_HANDLE(h);
+
+ if(h->source_mixer) {
+ float l = h->source_mixer->level(c);
+ if(l < -1000) return INVALID_MIXER_LEVEL;
+ *level = l;
+ return 0;
+ }
+
+ return MISSING_HANDLE;
+}
+
+int aio_get_capture_mixer_level_range(struct aio_t *h, float *min, float *max)
+{
+ CHECK_HANDLE(h);
+
+ if(h->source_mixer) {
+ Mixer::range_t r = h->source_mixer->range();
+ *min = r.min;
+ *max = r.max;
+ return 0;
+ }
+
+ return MISSING_HANDLE;
+}
+
+int aio_get_samplerate(struct aio_t *h)
+{
+ CHECK_HANDLE(h);
+
+ if(h->source) return h->source->samplerate();
+ else if(h->sink) return h->sink->samplerate();
+
+ return MISSING_HANDLE;
+}
+
+int aio_close(struct aio_t *h)
+{
+ CHECK_HANDLE(h);
+
+ h->magic = 0;
+ if(h->source) delete h->source;
+ if(h->source_mixer) delete h->source_mixer;
+ if(h->sink) delete h->sink;
+ if(h->sink_mixer) delete h->sink_mixer;
+ delete h;
+
+ return 0;
+}
+
+#ifdef __cplusplus
+}
+#endif