summaryrefslogtreecommitdiffstats
path: root/artsc/artsc.c
diff options
context:
space:
mode:
Diffstat (limited to 'artsc/artsc.c')
-rw-r--r--artsc/artsc.c226
1 files changed, 226 insertions, 0 deletions
diff --git a/artsc/artsc.c b/artsc/artsc.c
new file mode 100644
index 0000000..61a02b6
--- /dev/null
+++ b/artsc/artsc.c
@@ -0,0 +1,226 @@
+ /*
+
+ 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ */
+
+#include "artsc.h"
+#include "ltdl.h"
+#include <assert.h>
+
+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";
+}