/* -*- 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