From 4f6b15ea26b5fa09f300f67e4ce1057c2b39a3aa Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Thu, 25 Sep 2014 17:08:44 +0200 Subject: New API, new name, new version. --- src/audioio.cc | 287 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 287 insertions(+) create mode 100644 src/audioio.cc (limited to 'src/audioio.cc') 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 -- cgit v1.2.3