/* Copyright (C) 2000 Stefan Westerfeld stefan@space.twc.de This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "artsc.h" #include "ltdl.h" #include typedef int (*backend_init_ptr)(); typedef int (*backend_suspend_ptr)(); typedef int (*backend_suspended_ptr)(); typedef void (*backend_free_ptr)(); typedef arts_stream_t (*backend_play_stream_ptr)(int,int,int,const char*); typedef arts_stream_t (*backend_record_stream_ptr)(int,int,int,const char*); typedef void (*backend_close_stream_ptr)(arts_stream_t); typedef int (*backend_read_ptr)(arts_stream_t,void*,int); typedef int (*backend_write_ptr)(arts_stream_t,const void*,int); typedef int (*backend_stream_set_ptr)(arts_stream_t, arts_parameter_t, int); typedef int (*backend_stream_get_ptr)(arts_stream_t, arts_parameter_t); static struct arts_backend { int available; int refcnt; lt_dlhandle handle; backend_init_ptr init; backend_suspend_ptr suspend; backend_suspended_ptr suspended; backend_free_ptr free; backend_play_stream_ptr play_stream; backend_record_stream_ptr record_stream; backend_close_stream_ptr close_stream; backend_read_ptr read; backend_write_ptr write; backend_stream_set_ptr stream_set; backend_stream_get_ptr stream_get; } backend = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; static void arts_backend_ref() { if(backend.refcnt == 0) { lt_dlinit(); backend.handle = lt_dlopen(ARTSC_BACKEND); if(backend.handle) { backend.init = (backend_init_ptr) lt_dlsym(backend.handle, "arts_backend_init"); backend.suspend = (backend_suspend_ptr) lt_dlsym(backend.handle, "arts_backend_suspend"); backend.suspended = (backend_suspended_ptr) lt_dlsym(backend.handle, "arts_backend_suspended"); backend.free = (backend_free_ptr) lt_dlsym(backend.handle, "arts_backend_free"); backend.play_stream = (backend_play_stream_ptr) lt_dlsym(backend.handle, "arts_backend_play_stream"); backend.record_stream = (backend_record_stream_ptr) lt_dlsym(backend.handle, "arts_backend_record_stream"); backend.close_stream = (backend_close_stream_ptr) lt_dlsym(backend.handle, "arts_backend_close_stream"); backend.write = (backend_write_ptr) lt_dlsym(backend.handle, "arts_backend_write"); backend.read = (backend_read_ptr) lt_dlsym(backend.handle, "arts_backend_read"); backend.stream_set = (backend_stream_set_ptr) lt_dlsym(backend.handle, "arts_backend_stream_set"); backend.stream_get = (backend_stream_get_ptr) lt_dlsym(backend.handle, "arts_backend_stream_get"); } if(backend.handle && backend.init && backend.free && backend.play_stream && backend.record_stream && backend.close_stream && backend.write && backend.read && backend.stream_set && backend.stream_get && backend.suspend) backend.available = 1; else backend.available = 0; } backend.refcnt++; } static void arts_backend_release() { assert(backend.refcnt > 0); backend.refcnt--; if(backend.refcnt == 0) { if(backend.available) { backend.available = 0; if(backend.handle) lt_dlclose(backend.handle); } lt_dlexit(); } } int arts_init() { int rc = ARTS_E_NOBACKEND; arts_backend_ref(); if(backend.available) rc = backend.init(); /* init failed: the user may not call other arts_xxx functions now */ if(rc < 0) arts_backend_release(); return rc; } int arts_suspend() { int rc = ARTS_E_NOBACKEND; if(backend.available) rc = backend.suspend(); return rc; } int arts_suspended() { int rc = ARTS_E_NOBACKEND; if(backend.available && backend.suspended) rc = backend.suspended(); return rc; } void arts_free() { if(backend.available) { backend.free(); arts_backend_release(); } } arts_stream_t arts_play_stream(int rate, int bits, int channels, const char *name) { arts_stream_t rc = 0; if(backend.available) rc = backend.play_stream(rate,bits,channels,name); return rc; } arts_stream_t arts_record_stream(int rate, int bits, int channels, const char *name) { arts_stream_t rc = 0; if(backend.available) rc = backend.record_stream(rate,bits,channels,name); return rc; } void arts_close_stream(arts_stream_t stream) { if(backend.available) backend.close_stream(stream); } int arts_read(arts_stream_t stream, void *buffer, int count) { int rc = ARTS_E_NOBACKEND; if(backend.available) rc = backend.read(stream,buffer,count); return rc; } int arts_write(arts_stream_t stream, const void *buffer, int count) { int rc = ARTS_E_NOBACKEND; if(backend.available) rc = backend.write(stream,buffer,count); return rc; } int arts_stream_set(arts_stream_t stream, arts_parameter_t param, int value) { int rc = ARTS_E_NOBACKEND; if(backend.available) rc = backend.stream_set(stream,param,value); return rc; } int arts_stream_get(arts_stream_t stream, arts_parameter_t param) { int rc = ARTS_E_NOBACKEND; if(backend.available) rc = backend.stream_get(stream,param); return rc; } const char *arts_error_text(int errorcode) { switch(errorcode) { case 0: return "success"; case ARTS_E_NOSERVER: return "can't connect to aRts soundserver"; case ARTS_E_NOBACKEND: return "loading the aRts backend \"" ARTSC_BACKEND "\" failed"; case ARTS_E_NOIMPL: return "this aRts function is not yet implemented"; case ARTS_E_NOINIT: return "need to use arts_init() before using other functions"; case ARTS_E_NOSTREAM: return "you passed no valid aRts stream to a function"; } return "unknown arts error happened"; }