//libartsc.c: /* * Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2012 * The code (may) include prototypes and comments (and maybe * other code fragements) from libarts*. They are mostly copyrighted by: * Stefan Westerfeld * * This file is part of libroararts 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. * * NOTE for everyone want's to change something and send patches: * read README and HACKING! There a addition information on * the license of this document you need to read before you send * any patches. * * NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc * or libpulse*: * The libs libroaresd, libroararts and libroarpulse link this libroar * and are therefore GPL. Because of this it may be illigal to use * them with any software that uses libesd, libartsc or libpulse*. */ #include #include static struct roar_connection _libroarartsc_connection[1]; struct _libroarartsc_stream { roar_vs_t * vss; int block_size; int dir; }; int arts_init(void) { return roar_simple_connect(_libroarartsc_connection, NULL, "libroarartsc client"); } void arts_free(void) { roar_disconnect(_libroarartsc_connection); } /** * asks aRtsd to free the DSP device and return 1 if it was successful, * 0 if there were active non-suspendable modules */ int arts_suspend(void) { return roar_set_standby(_libroarartsc_connection, ROAR_STANDBY_ACTIVE) == 0 ? 1 : 0; } /** * asks aRtsd if the DSP device is free and return 1 if it is, * 0 if not */ int arts_suspended(void) { return roar_get_standby(_libroarartsc_connection) == ROAR_STANDBY_ACTIVE; } /** * converts an error code to a human readable error message * * @param errorcode the errorcode (from another arts function that failed) * @returns a text string with the error message */ const char *arts_error_text(int errorcode) { return roar_vs_strerr(errorcode); } static arts_stream_t _arts_stream(int rate, int bits, int channels, const char *name, int dir) { struct _libroarartsc_stream * s = roar_mm_malloc(sizeof(struct _libroarartsc_stream)); struct roar_stream * stream; struct roar_audio_info auinfo; struct roar_stream_info info; struct roar_keyval kv[1]; int err = ROAR_ERROR_NONE; if ( s == NULL ) return NULL; if ( (s->vss = roar_vs_new_from_con(_libroarartsc_connection, &err)) == NULL ) { roar_mm_free(s); return NULL; } memset(&auinfo, 0, sizeof(auinfo)); auinfo.rate = rate; auinfo.channels = channels; auinfo.bits = bits; auinfo.codec = ROAR_CODEC_DEFAULT; if ( roar_vs_stream(s->vss, &auinfo, dir, &err) == -1 ) { roar_vs_close(s->vss, ROAR_VS_TRUE, &err); roar_mm_free(s); return NULL; } s->dir = dir; stream = roar_vs_stream_obj(s->vss, &err); if ( roar_stream_get_info(_libroarartsc_connection, stream, &info) != -1 ) { s->block_size = info.block_size; } else { ROAR_WARN("_arts_stream(*): Can not get stream block size from server, assuming 1024 Byte."); s->block_size = 1024; } if ( name != NULL && *name ) { kv[0].key = "description"; kv[0].value = (char*)name; roar_vs_meta(s->vss, kv, 1, &err); } return (arts_stream_t) s; } /** * open a stream for playing * * @param rate the sampling rate (something like 44100) * @param bits how many bits each sample has (8 or 16) * @param channels how many channels, 1 is mono, 2 is stereo * @param name the name of the stream (these will be used so that the user can * assign streams to effects/mixer channels and similar) * * @return a stream */ arts_stream_t arts_play_stream(int rate, int bits, int channels, const char *name) { return _arts_stream(rate, bits, channels, name, ROAR_DIR_PLAY); } /** * open a stream for recording * * @param rate the sampling rate (something like 44100) * @param bits how many bits each sample has (8 or 16) * @param channels how many channels, 1 is mono, 2 is stereo * @param name the name of the stream (these will be used so that the user can * assign streams to effects/mixer channels and similar) * * @return a stream */ arts_stream_t arts_record_stream(int rate, int bits, int channels, const char *name) { return _arts_stream(rate, bits, channels, name, ROAR_DIR_RECORD); } /** * close a stream */ void arts_close_stream(arts_stream_t stream) { struct _libroarartsc_stream * s = (struct _libroarartsc_stream *) stream; if ( stream == NULL ) return; roar_vs_close(s->vss, ROAR_VS_TRUE, NULL); roar_mm_free(stream); } /** * read samples from stream * * @param stream a previously opened record stream * @param buffer a buffer with sample data * @param count the number of bytes contained in the buffer * * @returns number of read bytes on success or error code */ int arts_read(arts_stream_t stream, void *buffer, int count) { struct _libroarartsc_stream * s = (struct _libroarartsc_stream *) stream; if ( stream == NULL ) return -1; return roar_vs_read(s->vss, buffer, count, NULL); } /** * write samples to to stream * * @param stream a previously opened play stream * @param buffer a buffer with sample data * @param count the number of bytes contained in the buffer * * @returns number of written bytes on success or error code */ int arts_write(arts_stream_t stream, const void *buffer, int count) { struct _libroarartsc_stream * s = (struct _libroarartsc_stream *) stream; if ( !stream ) return -1; return roar_vs_write(s->vss, buffer, count, NULL); } /** * configure a parameter of a stream * * @param stream an opened record or play stream * @param parameter the parameter you want to modify * @param value the new value * * @returns the new value of the parameter (which may or may not be the value * you wanted to have), or an error code if something went wrong */ int arts_stream_set(arts_stream_t stream, arts_parameter_t param, int value) { struct _libroarartsc_stream * s = (struct _libroarartsc_stream *) stream; if ( stream == NULL ) return -1; if ( param == ARTS_P_BLOCKING ) { if ( roar_vs_blocking(s->vss, value ? ROAR_VS_TRUE : ROAR_VS_FALSE, NULL) == -1 ) return -1; return arts_stream_get(stream, param); } return arts_stream_get(stream, param); } /** * query a parameter of a stream * * @param stream an opened record or play stream * @param parameter the parameter you want to query * * @returns the value of the parameter, or an error code */ int arts_stream_get(arts_stream_t stream, arts_parameter_t param) { struct _libroarartsc_stream * s = (struct _libroarartsc_stream *) stream; struct roar_vio_select vios; struct roar_vio_selecttv rtv; int events; if ( stream == NULL ) return -1; if ( param == ARTS_P_PACKET_SIZE ) { return s->block_size; } else if ( param == ARTS_P_BUFFER_SPACE ) { rtv.sec = 0; rtv.nsec = 1000; events = s->dir == ROAR_DIR_PLAY ? ROAR_VIO_SELECT_WRITE : ROAR_VIO_SELECT_READ; ROAR_VIO_SELECT_SETVIO(&vios, roar_vs_vio_obj(s->vss, NULL), events); if ( roar_vio_select(&vios, 1, &rtv, NULL) == 1 ) return s->block_size; return 0; } else if ( param == ARTS_P_BUFFER_SIZE ) { return s->block_size*2; } else if ( param == ARTS_P_PACKET_COUNT ) { return 1; } else if ( param == ARTS_P_BLOCKING ) { return roar_vs_blocking(s->vss, ROAR_VS_ASK, NULL) == ROAR_VS_TRUE ? 1 : 0; } return -1; } //ll