//driver_artsc.c: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2011 * * This file is part of roard a part of RoarAudio, * a cross-platform sound system for both, home and professional use. * See README for details. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * as published by the Free Software Foundation. * * RoarAudio 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #include "roard.h" #ifdef ROAR_HAVE_LIBARTSC #define INIT +1 #define SHUTDOWN -1 static int driver_artsc_init_shutdown (int action) { static int state = 0; if ( action != INIT && action != SHUTDOWN ) return -1; if ( state == 0 && action == INIT ) { if ( arts_init() != 0 ) return -1; } else if ( state == 1 && action == SHUTDOWN ) { arts_free(); } state += action; return 0; } int driver_artsc_open_vio(struct roar_vio_calls * inst, char * device, struct roar_audio_info * info, int fh, struct roar_stream_server * sstream) { struct roar_artsc * self = NULL; (void)sstream; if ( fh != -1 || device != NULL ) return -1; self = roar_mm_malloc(sizeof(struct roar_artsc)); if ( self == NULL ) return -1; memset(self, 0, sizeof(struct roar_artsc)); if ( driver_artsc_init_shutdown(INIT) == -1 ) { roar_mm_free(self); return -1; } info->codec = ROAR_CODEC_DEFAULT; self->info = info; self->stream = arts_play_stream(info->rate, info->bits, info->channels, "roard"); if ( self->stream == NULL ) { roar_mm_free(self); driver_artsc_init_shutdown(SHUTDOWN); return -1; } memset(inst, 0, sizeof(struct roar_vio_calls)); inst->inst = (void*) self; inst->write = driver_artsc_write; inst->close = driver_artsc_close; inst->ctl = driver_artsc_ctl; inst->nonblock = driver_artsc_nonblock; return 0; } ssize_t driver_artsc_write (struct roar_vio_calls * vio, void *buf, size_t count) { struct roar_artsc * self = vio->inst; int ret = arts_write(self->stream, buf, count); if ( ret >= 0 ) return ret; return -1; } int driver_artsc_close (struct roar_vio_calls * vio) { struct roar_artsc * self = vio->inst; arts_close_stream(self->stream); roar_mm_free(self); return driver_artsc_init_shutdown(SHUTDOWN); } int driver_artsc_nonblock(struct roar_vio_calls * vio, int state) { struct roar_artsc * self = vio->inst; int ret; switch (state) { case ROAR_SOCKET_NONBLOCK: ret = arts_stream_set(self->stream, ARTS_P_BLOCKING, 0); if ( ret == 0 ) return 0; break; case ROAR_SOCKET_BLOCK: ret = arts_stream_set(self->stream, ARTS_P_BLOCKING, 1); if ( ret == 1 ) return 0; break; } return -1; } int driver_artsc_ctl (struct roar_vio_calls * vio, int cmd, void * data) { struct roar_artsc * self = vio->inst; ssize_t bps; int ret; uint_least32_t tmp; switch (cmd) { case ROAR_VIO_CTL_GET_DBLKSIZE: ret = arts_stream_get(self->stream, ARTS_P_PACKET_SIZE); if ( ret > 0 ) { *(uint_least32_t *)data = ret; return 0; } break; case ROAR_VIO_CTL_GET_DELAY: ret = arts_stream_get(self->stream, ARTS_P_TOTAL_LATENCY); if ( ret < 0 ) return -1; bps = roar_info2bitspersec(self->info); if ( bps < 0 ) return -1; tmp = bps / (ssize_t)8; tmp *= ret; tmp /= (uint_least32_t)1000; *(uint_least32_t *)data = tmp; return 0; default: return -1; } return -1; } #endif //ll