summaryrefslogtreecommitdiffstats
path: root/polyp
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2004-08-14 20:25:32 +0000
committerLennart Poettering <lennart@poettering.net>2004-08-14 20:25:32 +0000
commit22cb23eedb2eae7c79dc8fcf395be08bfc666256 (patch)
treef0993d4a26cb6e311d052b40ac5b8efc1239c145 /polyp
parent1c2ec47cf1506ad1c75c088d476ae382170df62c (diff)
implement proper refcounting in polyplib
split polyplib to multiple modules add some prelimenary documentation add doxygen support git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@123 fefdeb5f-60dc-0310-8127-8f9354f1896f
Diffstat (limited to 'polyp')
-rw-r--r--polyp/Makefile.am25
-rw-r--r--polyp/cdecl.h21
-rw-r--r--polyp/glib-mainloop.h20
-rw-r--r--polyp/llist.h39
-rw-r--r--polyp/mainloop-api.h44
-rw-r--r--polyp/mainloop.h5
-rw-r--r--polyp/memblock.c42
-rw-r--r--polyp/memblock.h4
-rw-r--r--polyp/native-common.h18
-rw-r--r--polyp/pacat.c150
-rw-r--r--polyp/pactl.c146
-rw-r--r--polyp/polyplib-context.c1486
-rw-r--r--polyp/polyplib-context.h182
-rw-r--r--polyp/polyplib-def.h17
-rw-r--r--polyp/polyplib-error.h12
-rw-r--r--polyp/polyplib-internal.h1528
-rw-r--r--polyp/polyplib-introspect.c1651
-rw-r--r--polyp/polyplib-introspect.h109
-rw-r--r--polyp/polyplib-operation.c78
-rw-r--r--polyp/polyplib-operation.h56
-rw-r--r--polyp/polyplib-sample.c1550
-rw-r--r--polyp/polyplib-sample.h178
-rw-r--r--polyp/polyplib-scache.c1495
-rw-r--r--polyp/polyplib-scache.h162
-rw-r--r--polyp/polyplib-simple.c68
-rw-r--r--polyp/polyplib-simple.h33
-rw-r--r--polyp/polyplib-stream.c1556
-rw-r--r--polyp/polyplib-stream.h178
-rw-r--r--polyp/polyplib-subscribe.c1514
-rw-r--r--polyp/polyplib-subscribe.h158
-rw-r--r--polyp/polyplib.c1550
-rw-r--r--polyp/polyplib.h156
-rw-r--r--polyp/sample-util.c7
-rw-r--r--polyp/sample-util.h4
-rw-r--r--polyp/sample.c8
-rw-r--r--polyp/sample.h21
-rw-r--r--polyp/socket-client.c2
-rw-r--r--polyp/socket-client.h2
-rw-r--r--polyp/tagstruct.h2
-rw-r--r--polyp/xmalloc.c29
-rw-r--r--polyp/xmalloc.h2
41 files changed, 1597 insertions, 12711 deletions
diff --git a/polyp/Makefile.am b/polyp/Makefile.am
index ce753da4..7f70ec9d 100644
--- a/polyp/Makefile.am
+++ b/polyp/Makefile.am
@@ -25,12 +25,19 @@ polypincludedir=$(includedir)/polyp
EXTRA_DIST = polypaudio.pa depmod.py
bin_PROGRAMS = polypaudio pacat pactl
-noinst_PROGRAMS = pacat-simple parec-simple mainloop-test mainloop-test-glib
+noinst_PROGRAMS = mainloop-test mainloop-test-glib pacat-simple parec-simple
polypinclude_HEADERS=polyplib.h \
polyplib-def.h \
polyplib-simple.h \
polyplib-error.h \
+ polyplib-stream.h \
+ polyplib-context.h \
+ polyplib-introspect.h \
+ polyplib-subscribe.h \
+ polyplib-operation.h \
+ polyplib-scache.h \
+ cdecl.h \
mainloop-api.h \
mainloop.h \
mainloop-signal.h \
@@ -72,10 +79,11 @@ pkglib_LTLIBRARIES=libiochannel.la \
module-x11-bell.la
lib_LTLIBRARIES=libpolyp.la \
- libpolyp-simple.la \
libpolyp-error.la \
libpolyp-mainloop.la \
- libpolyp-mainloop-glib.la
+ libpolyp-mainloop-glib.la \
+ libpolyp-simple.la
+
polypaudio_SOURCES = idxset.c idxset.h \
queue.c queue.h \
@@ -261,7 +269,7 @@ module_x11_bell_la_SOURCES = module-x11-bell.c
module_x11_bell_la_LDFLAGS = -module -avoid-version
module_x11_bell_la_LIBADD = $(AM_LIBADD) -lX11 -L/usr/X11R6/lib
-libpolyp_la_SOURCES = polyplib.c polyplib.h \
+libpolyp_la_SOURCES = polyplib.h \
polyplib-def.h \
tagstruct.c tagstruct.h \
iochannel.c iochannel.h \
@@ -281,7 +289,14 @@ libpolyp_la_SOURCES = polyplib.c polyplib.h \
socket-util.c socket-util.h \
native-common.h \
sample.c sample.h \
- xmalloc.c xmalloc.h
+ xmalloc.c xmalloc.h \
+ polyplib-operation.c polyplib-operation.h \
+ polyplib-context.c polyplib-context.h \
+ polyplib-stream.c polyplib-stream.h \
+ polyplib-introspect.c polyplib-introspect.h \
+ polyplib-scache.c polyplib-scache.h \
+ polyplib-subscribe.c polyplib-subscribe.h \
+ cdecl.h
libpolyp_la_CFLAGS = $(AM_CFLAGS)
libpolyp_mainloop_la_SOURCES = mainloop-api.h mainloop-api.c \
diff --git a/polyp/cdecl.h b/polyp/cdecl.h
new file mode 100644
index 00000000..39880a47
--- /dev/null
+++ b/polyp/cdecl.h
@@ -0,0 +1,21 @@
+#ifndef foocdeclhfoo
+#define foocdeclhfoo
+
+/** \file
+ * C++ compatibility support */
+
+#ifdef __cplusplus
+/** If using C++ this macro enables C mode, otherwise does nothing */
+#define PA_C_DECL_BEGIN extern "C" {
+/** If using C++ this macros switches back to C++ mode, otherwise does nothing */
+#define PA_C_DECL_END }
+
+#else
+/** If using C++ this macro enables C mode, otherwise does nothing */
+#define PA_C_DECL_BEGIN
+/** If using C++ this macros switches back to C++ mode, otherwise does nothing */
+#define PA_C_DECL_END
+
+#endif
+
+#endif
diff --git a/polyp/glib-mainloop.h b/polyp/glib-mainloop.h
index 7655108a..c67e72bd 100644
--- a/polyp/glib-mainloop.h
+++ b/polyp/glib-mainloop.h
@@ -4,20 +4,26 @@
#include <glib.h>
#include "mainloop-api.h"
+#include "cdecl.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
+/** \file
+ * GLIB main loop support */
+
+PA_C_DECL_BEGIN
+/** \struct pa_glib_mainloop
+ * A GLIB main loop object */
struct pa_glib_mainloop;
+/** Create a new GLIB main loop object for the specified GLIB main loop context. If c is NULL the default context is used. */
struct pa_glib_mainloop *pa_glib_mainloop_new(GMainContext *c);
+
+/** Free the GLIB main loop object */
void pa_glib_mainloop_free(struct pa_glib_mainloop* g);
+
+/** Return the abstract main loop API vtable for the GLIB main loop object */
struct pa_mainloop_api* pa_glib_mainloop_get_api(struct pa_glib_mainloop *g);
-
-#ifdef __cplusplus
-}
-#endif
+PA_C_DECL_BEGIN
#endif
diff --git a/polyp/llist.h b/polyp/llist.h
new file mode 100644
index 00000000..1f145de2
--- /dev/null
+++ b/polyp/llist.h
@@ -0,0 +1,39 @@
+#ifndef foollistfoo
+#define foollistfoo
+
+#define PA_LLIST_HEAD(t,name) t *name
+
+#define PA_LLIST_FIELDS(t) t *next, *prev;
+
+#define PA_LLIST_HEAD_INIT(t,item) do { (item) = NULL; } while(0)
+
+#define PA_LLIST_INIT(t,item) do { \
+ t *_item = (item); \
+ assert(_item); \
+ _item->prev = _item->next = NULL; \
+ } while(0)
+
+#define PA_LLIST_PREPEND(t,head,item) do { \
+ t **_head = &(head), *_item = (item); \
+ assert(_item); \
+ if ((_item->next = *_head)) \
+ _item->next->prev = _item; \
+ _item->prev = NULL; \
+ *_head = _item; \
+ } while (0)
+
+#define PA_LLIST_REMOVE(t,head,item) do { \
+ t **_head = &(head), *_item = (item); \
+ assert(_item); \
+ if (_item->next) \
+ _item->next->prev = _item->prev; \
+ if (_item->prev) \
+ _item->prev->next = _item->next; \
+ else {\
+ assert(*_head == _item); \
+ *_head = _item->next; \
+ } \
+ _item->next = _item->prev = NULL; \
+ } while(0)
+
+#endif
diff --git a/polyp/mainloop-api.h b/polyp/mainloop-api.h
index 1b9e2783..97ab6a68 100644
--- a/polyp/mainloop-api.h
+++ b/polyp/mainloop-api.h
@@ -22,26 +22,37 @@
USA.
***/
-#include <time.h>
#include <sys/time.h>
+#include <time.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
+#include "cdecl.h"
+PA_C_DECL_BEGIN
+
+/** A bitmask for IO events */
enum pa_io_event_flags {
- PA_IO_EVENT_NULL = 0,
- PA_IO_EVENT_INPUT = 1,
- PA_IO_EVENT_OUTPUT = 2,
- PA_IO_EVENT_HANGUP = 4,
- PA_IO_EVENT_ERROR = 8,
+ PA_IO_EVENT_NULL = 0, /**< No event */
+ PA_IO_EVENT_INPUT = 1, /**< Input event */
+ PA_IO_EVENT_OUTPUT = 2, /**< Output event */
+ PA_IO_EVENT_HANGUP = 4, /**< Hangup event */
+ PA_IO_EVENT_ERROR = 8, /**< Error event */
};
+/** \struct pa_io_event
+ * An IO event source object */
struct pa_io_event;
+
+/** \struct pa_defer_event
+ * A deferred event source object. Events of this type are triggered once in every main loop iteration */
struct pa_defer_event;
+
+/** \struct pa_time_event
+ * A timer event source object */
struct pa_time_event;
+/** An abstract mainloop API vtable */
struct pa_mainloop_api {
+ /** A pointer to some private, arbitrary data of the main loop implementation */
void *userdata;
/* IO sources */
@@ -56,20 +67,25 @@ struct pa_mainloop_api {
void (*time_free)(struct pa_time_event* e);
void (*time_set_destroy)(struct pa_time_event *e, void (*callback) (struct pa_mainloop_api*a, struct pa_time_event *e, void *userdata));
- /* Deferred sources */
+ /** Create a new deferred event source object */
struct pa_defer_event* (*defer_new)(struct pa_mainloop_api*a, void (*callback) (struct pa_mainloop_api*a, struct pa_defer_event* e, void *userdata), void *userdata);
+
+ /** Enable or disable a deferred event source temporarily */
void (*defer_enable)(struct pa_defer_event* e, int b);
+
+ /** Free a deferred event source object */
void (*defer_free)(struct pa_defer_event* e);
+
+ /** Set a function that is called when the deferred event source is destroyed. Use this to free the userdata argument if required */
void (*defer_set_destroy)(struct pa_defer_event *e, void (*callback) (struct pa_mainloop_api*a, struct pa_defer_event *e, void *userdata));
- /* Exit mainloop */
+ /** Exit the main loop and return the specfied retval*/
void (*quit)(struct pa_mainloop_api*a, int retval);
};
+/** Run the specified callback function once from the main loop using an anonymous defer event. */
void pa_mainloop_api_once(struct pa_mainloop_api*m, void (*callback)(struct pa_mainloop_api*m, void *userdata), void *userdata);
-#ifdef __cplusplus
-}
-#endif
+PA_C_DECL_END
#endif
diff --git a/polyp/mainloop.h b/polyp/mainloop.h
index 58448c3e..4a4c85df 100644
--- a/polyp/mainloop.h
+++ b/polyp/mainloop.h
@@ -23,6 +23,9 @@
***/
#include "mainloop-api.h"
+#include "cdecl.h"
+
+PA_C_DECL_BEGIN
struct pa_mainloop;
@@ -34,4 +37,6 @@ int pa_mainloop_run(struct pa_mainloop *m, int *retval);
struct pa_mainloop_api* pa_mainloop_get_api(struct pa_mainloop*m);
+PA_C_DECL_END
+
#endif
diff --git a/polyp/memblock.c b/polyp/memblock.c
index 0571f5da..a4452efa 100644
--- a/polyp/memblock.c
+++ b/polyp/memblock.c
@@ -39,6 +39,7 @@ struct pa_memblock *pa_memblock_new(size_t length) {
b->ref = 1;
b->length = length;
b->data = b+1;
+ b->free_cb = NULL;
memblock_count++;
memblock_total += length;
return b;
@@ -50,6 +51,7 @@ struct pa_memblock *pa_memblock_new_fixed(void *d, size_t length) {
b->ref = 1;
b->length = length;
b->data = d;
+ b->free_cb = NULL;
memblock_count++;
memblock_total += length;
return b;
@@ -61,6 +63,21 @@ struct pa_memblock *pa_memblock_new_dynamic(void *d, size_t length) {
b->ref = 1;
b->length = length;
b->data = d;
+ b->free_cb = NULL;
+ memblock_count++;
+ memblock_total += length;
+ return b;
+}
+
+struct pa_memblock *pa_memblock_new_user(void *d, size_t length, void (*free_cb)(void *p)) {
+ struct pa_memblock *b;
+ assert(d && length && free_cb);
+ b = pa_xmalloc(sizeof(struct pa_memblock));
+ b->type = PA_MEMBLOCK_USER;
+ b->ref = 1;
+ b->length = length;
+ b->data = d;
+ b->free_cb = free_cb;
memblock_count++;
memblock_total += length;
return b;
@@ -74,31 +91,28 @@ struct pa_memblock* pa_memblock_ref(struct pa_memblock*b) {
void pa_memblock_unref(struct pa_memblock*b) {
assert(b && b->ref >= 1);
- b->ref--;
-
- if (b->ref == 0) {
- if (b->type == PA_MEMBLOCK_DYNAMIC)
- pa_xfree(b->data);
+ if ((--(b->ref)) == 0) {
memblock_count--;
memblock_total -= b->length;
+ if (b->type == PA_MEMBLOCK_USER) {
+ assert(b->free_cb);
+ b->free_cb(b->data);
+ } else if (b->type == PA_MEMBLOCK_DYNAMIC)
+ pa_xfree(b->data);
+
pa_xfree(b);
}
}
void pa_memblock_unref_fixed(struct pa_memblock *b) {
- void *d;
-
- assert(b && b->ref >= 1);
+ assert(b && b->ref >= 1 && b->type == PA_MEMBLOCK_FIXED);
- if (b->ref == 1) {
+ if (b->ref == 1)
pa_memblock_unref(b);
- return;
- } else {
- d = pa_xmalloc(b->length);
- memcpy(d, b->data, b->length);
- b->data = d;
+ else {
+ b->data = pa_xmemdup(b->data, b->length);
b->type = PA_MEMBLOCK_DYNAMIC;
b->ref--;
}
diff --git a/polyp/memblock.h b/polyp/memblock.h
index 4bb02977..6e79aa3e 100644
--- a/polyp/memblock.h
+++ b/polyp/memblock.h
@@ -25,18 +25,20 @@
#include <sys/types.h>
#include <inttypes.h>
-enum pa_memblock_type { PA_MEMBLOCK_FIXED, PA_MEMBLOCK_APPENDED, PA_MEMBLOCK_DYNAMIC };
+enum pa_memblock_type { PA_MEMBLOCK_FIXED, PA_MEMBLOCK_APPENDED, PA_MEMBLOCK_DYNAMIC, PA_MEMBLOCK_USER };
struct pa_memblock {
enum pa_memblock_type type;
unsigned ref;
size_t length;
void *data;
+ void (*free_cb)(void *p);
};
struct pa_memblock *pa_memblock_new(size_t length);
struct pa_memblock *pa_memblock_new_fixed(void *data, size_t length);
struct pa_memblock *pa_memblock_new_dynamic(void *data, size_t length);
+struct pa_memblock *pa_memblock_new_user(void *data, size_t length, void (*free_cb)(void *p));
void pa_memblock_unref(struct pa_memblock*b);
struct pa_memblock* pa_memblock_ref(struct pa_memblock*b);
diff --git a/polyp/native-common.h b/polyp/native-common.h
index 4d5ab53d..fa3213d0 100644
--- a/polyp/native-common.h
+++ b/polyp/native-common.h
@@ -64,6 +64,9 @@ enum {
PA_COMMAND_SUBSCRIBE,
PA_COMMAND_SUBSCRIBE_EVENT,
+
+ PA_COMMAND_SET_SINK_VOLUME,
+ PA_COMMAND_SET_SINK_INPUT_VOLUME,
PA_COMMAND_MAX
};
@@ -90,13 +93,14 @@ enum {
#define PA_NATIVE_COOKIE_FILE ".polypaudio-cookie"
enum pa_subscription_mask {
- PA_SUBSCRIPTION_FACILITY_SINK = 1,
- PA_SUBSCRIPTION_FACILITY_SOURCE = 2,
- PA_SUBSCRIPTION_FACILITY_SINK_INPUT = 4,
- PA_SUBSCRIPTION_FACILITY_SOURCE_OUTPUT = 8,
- PA_SUBSCRIPTION_FACILITY_MODULE = 16,
- PA_SUBSCRIPTION_FACILITY_CLIENT = 32,
- PA_SUBSCRIPTION_FACILITY_SAMPLE_CACHE = 64,
+ PA_SUBSCRIPTION_MASK_NULL = 0,
+ PA_SUBSCRIPTION_MASK_SINK = 1,
+ PA_SUBSCRIPTION_MASK_SOURCE = 2,
+ PA_SUBSCRIPTION_MASK_SINK_INPUT = 4,
+ PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT = 8,
+ PA_SUBSCRIPTION_MASK_MODULE = 16,
+ PA_SUBSCRIPTION_MASK_CLIENT = 32,
+ PA_SUBSCRIPTION_MASK_SAMPLE_CACHE = 64,
};
enum pa_subscription_event_type {
diff --git a/polyp/pacat.c b/polyp/pacat.c
index 4d8605c7..5d29451a 100644
--- a/polyp/pacat.c
+++ b/polyp/pacat.c
@@ -52,18 +52,6 @@ static void quit(int ret) {
mainloop_api->quit(mainloop_api, ret);
}
-static void context_die_callback(struct pa_context *c, void *userdata) {
- assert(c);
- fprintf(stderr, "Connection to server shut down, exiting.\n");
- quit(1);
-}
-
-static void stream_die_callback(struct pa_stream *s, void *userdata) {
- assert(s);
- fprintf(stderr, "Stream deleted, exiting.\n");
- quit(1);
-}
-
static void do_stream_write(size_t length) {
size_t l;
assert(length);
@@ -75,7 +63,7 @@ static void do_stream_write(size_t length) {
if (l > buffer_length)
l = buffer_length;
- pa_stream_write(stream, buffer+buffer_index, l);
+ pa_stream_write(stream, buffer+buffer_index, l, NULL);
buffer_length -= l;
buffer_index += l;
@@ -115,63 +103,97 @@ static void stream_read_callback(struct pa_stream *s, const void*data, size_t le
buffer_index = 0;
}
-static void stream_complete_callback(struct pa_stream*s, int success, void *userdata) {
+static void stream_state_callback(struct pa_stream *s, void *userdata) {
assert(s);
- if (!success) {
- fprintf(stderr, "Stream creation failed: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s))));
- quit(1);
- return;
+ switch (pa_stream_get_state(s)) {
+ case PA_STREAM_CREATING:
+ break;
+
+ case PA_STREAM_READY:
+ fprintf(stderr, "Stream successfully created\n");
+ break;
+
+ case PA_STREAM_TERMINATED:
+ quit(0);
+ break;
+
+ case PA_STREAM_FAILED:
+ default:
+ fprintf(stderr, "Stream errror: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s))));
+ quit(1);
}
-
- fprintf(stderr, "Stream created.\n");
}
-static void context_complete_callback(struct pa_context *c, int success, void *userdata) {
+static void context_state_callback(struct pa_context *c, void *userdata) {
static const struct pa_sample_spec ss = {
.format = PA_SAMPLE_S16LE,
.rate = 44100,
.channels = 2
};
-
- assert(c && !stream);
- if (!success) {
- fprintf(stderr, "Connection failed: %s\n", pa_strerror(pa_context_errno(c)));
- goto fail;
- }
+ assert(c);
- fprintf(stderr, "Connection established.\n");
-
- if (!(stream = pa_stream_new(c, mode == PLAYBACK ? PA_STREAM_PLAYBACK : PA_STREAM_RECORD, NULL, "pacat", &ss, NULL, stream_complete_callback, NULL))) {
- fprintf(stderr, "pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(c)));
- goto fail;
+ switch (pa_context_get_state(c)) {
+ case PA_CONTEXT_CONNECTING:
+ case PA_CONTEXT_AUTHORIZING:
+ case PA_CONTEXT_SETTING_NAME:
+ break;
+
+ case PA_CONTEXT_READY:
+
+ assert(c && !stream);
+ fprintf(stderr, "Connection established.\n");
+
+ stream = pa_stream_new(c, "pacat", &ss);
+ assert(stream);
+
+ pa_stream_set_state_callback(stream, stream_state_callback, NULL);
+ pa_stream_set_write_callback(stream, stream_write_callback, NULL);
+ pa_stream_set_read_callback(stream, stream_read_callback, NULL);
+
+ if (mode == PLAYBACK)
+ pa_stream_connect_playback(stream, NULL, NULL);
+ else
+ pa_stream_connect_record(stream, NULL, NULL);
+
+ break;
+
+ case PA_CONTEXT_TERMINATED:
+ quit(0);
+ break;
+
+ case PA_CONTEXT_FAILED:
+ default:
+ fprintf(stderr, "Connection failure: %s\n", pa_strerror(pa_context_errno(c)));
+ quit(1);
}
-
- pa_stream_set_die_callback(stream, stream_die_callback, NULL);
- pa_stream_set_write_callback(stream, stream_write_callback, NULL);
- pa_stream_set_read_callback(stream, stream_read_callback, NULL);
-
- return;
-
-fail:
- quit(1);
}
static void context_drain_complete(struct pa_context*c, void *userdata) {
- quit(0);
+ pa_context_disconnect(c);
}
-static void stream_drain_complete(struct pa_stream*s, void *userdata) {
+static void stream_drain_complete(struct pa_stream*s, int success, void *userdata) {
+ struct pa_operation *o;
+
+ if (!success) {
+ fprintf(stderr, "Failed to drain stream: %s\n", pa_strerror(pa_context_errno(context)));
+ quit(1);
+ }
+
fprintf(stderr, "Playback stream drained.\n");
- pa_stream_free(stream);
+ pa_stream_disconnect(stream);
+ pa_stream_unref(stream);
stream = NULL;
- if (pa_context_drain(context, context_drain_complete, NULL) < 0)
- quit(0);
- else
+ if (!(o = pa_context_drain(context, context_drain_complete, NULL)))
+ pa_context_disconnect(context);
+ else {
+ pa_operation_unref(o);
fprintf(stderr, "Draining connection to server.\n");
+ }
}
static void stdin_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) {
@@ -184,7 +206,7 @@ static void stdin_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int
return;
}
- if (!stream || !pa_stream_is_ready(stream) || !(l = w = pa_stream_writable_size(stream)))
+ if (!stream || pa_stream_get_state(stream) != PA_STREAM_READY || !(l = w = pa_stream_writable_size(stream)))
l = 4096;
buffer = malloc(l);
@@ -192,7 +214,7 @@ static void stdin_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int
if ((r = read(fd, buffer, l)) <= 0) {
if (r == 0) {
fprintf(stderr, "Got EOF.\n");
- pa_stream_drain(stream, stream_drain_complete, NULL);
+ pa_operation_unref(pa_stream_drain(stream, stream_drain_complete, NULL));
} else {
fprintf(stderr, "read() failed: %s\n", strerror(errno));
quit(1);
@@ -259,10 +281,11 @@ static void stream_get_latency_callback(struct pa_stream *s, uint32_t latency, v
}
static void sigusr1_signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) {
- if (mode == PLAYBACK) {
- fprintf(stderr, "Got SIGUSR1, requesting latency.\n");
- pa_stream_get_latency(stream, stream_get_latency_callback, NULL);
- }
+ if (mode != PLAYBACK)
+ return;
+
+ fprintf(stderr, "Got SIGUSR1, requesting latency.\n");
+ pa_operation_unref(pa_stream_get_latency(stream, stream_get_latency_callback, NULL));
}
int main(int argc, char *argv[]) {
@@ -306,12 +329,9 @@ int main(int argc, char *argv[]) {
goto quit;
}
- if (pa_context_connect(context, NULL, context_complete_callback, NULL) < 0) {
- fprintf(stderr, "pa_context_connext() failed.\n");
- goto quit;
- }
-
- pa_context_set_die_callback(context, context_die_callback, NULL);
+ pa_context_set_state_callback(context, context_state_callback, NULL);
+
+ pa_context_connect(context, NULL);
if (pa_mainloop_run(m, &ret) < 0) {
fprintf(stderr, "pa_mainloop_run() failed.\n");
@@ -320,15 +340,21 @@ int main(int argc, char *argv[]) {
quit:
if (stream)
- pa_stream_free(stream);
+ pa_stream_unref(stream);
+
if (context)
- pa_context_free(context);
+ pa_context_unref(context);
+ if (stdio_event) {
+ assert(mainloop_api);
+ mainloop_api->io_free(stdio_event);
+ }
+
if (m) {
pa_signal_done();
pa_mainloop_free(m);
}
-
+
if (buffer)
free(buffer);
diff --git a/polyp/pactl.c b/polyp/pactl.c
index 2f3a4833..0ff2aa90 100644
--- a/polyp/pactl.c
+++ b/polyp/pactl.c
@@ -68,31 +68,27 @@ static void quit(int ret) {
mainloop_api->quit(mainloop_api, ret);
}
-static void context_die_callback(struct pa_context *c, void *userdata) {
- assert(c);
- fprintf(stderr, "Connection to server shut down, exiting.\n");
- quit(1);
-}
static void context_drain_complete(struct pa_context *c, void *userdata) {
- assert(c);
- fprintf(stderr, "Connection to server shut down, exiting.\n");
- quit(0);
+ pa_context_disconnect(c);
}
static void drain(void) {
- if (pa_context_drain(context, context_drain_complete, NULL) < 0)
- quit(0);
+ struct pa_operation *o;
+ if (!(o = pa_context_drain(context, context_drain_complete, NULL)))
+ pa_context_disconnect(context);
+ else
+ pa_operation_unref(o);
}
-static void stat_callback(struct pa_context *c, uint32_t blocks, uint32_t total, void *userdata) {
- if (blocks == (uint32_t) -1) {
+static void stat_callback(struct pa_context *c, const struct pa_stat_info *i, void *userdata) {
+ if (!i) {
fprintf(stderr, "Failed to get statistics: %s\n", pa_strerror(pa_context_errno(c)));
quit(1);
return;
}
- fprintf(stderr, "Currently in use: %u blocks containing %u bytes total.\n", blocks, total);
+ fprintf(stderr, "Currently in use: %u blocks containing %u bytes total.\n", i->memblock_count, i->memblock_total);
drain();
}
@@ -116,22 +112,23 @@ static void remove_sample_callback(struct pa_context *c, int success, void *user
drain();
}
-static void stream_die_callback(struct pa_stream *s, void *userdata) {
- assert(s);
- fprintf(stderr, "Stream deleted, exiting.\n");
- quit(1);
-}
-
-static void finish_sample_callback(struct pa_stream *s, int success, void *userdata) {
+static void stream_state_callback(struct pa_stream *s, void *userdata) {
assert(s);
- if (!success) {
- fprintf(stderr, "Failed to upload sample: %s\n", pa_strerror(pa_context_errno(context)));
- quit(1);
- return;
+ switch (pa_stream_get_state(s)) {
+ case PA_STREAM_CREATING:
+ case PA_STREAM_READY:
+ break;
+
+ case PA_STREAM_TERMINATED:
+ drain();
+ break;
+
+ case PA_STREAM_FAILED:
+ default:
+ fprintf(stderr, "Failed to upload sample: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s))));
+ quit(1);
}
-
- drain();
}
static void stream_write_callback(struct pa_stream *s, size_t length, void *userdata) {
@@ -151,58 +148,55 @@ static void stream_write_callback(struct pa_stream *s, size_t length, void *user
quit(1);
}
- pa_stream_write(s, d, length);
- free(d);
+ pa_stream_write(s, d, length, free);
sample_length -= length;
if (sample_length <= 0) {
pa_stream_set_write_callback(sample_stream, NULL, NULL);
- pa_stream_finish_sample(sample_stream, finish_sample_callback, NULL);
- }
-}
-
-static void upload_callback(struct pa_stream *s, int success, void *userdata) {
- if (!success) {
- fprintf(stderr, "Failed to upload sample: %s\n", pa_strerror(pa_context_errno(context)));
- quit(1);
+ pa_stream_finish_upload(sample_stream);
}
}
-static void context_complete_callback(struct pa_context *c, int success, void *userdata) {
+static void context_state_callback(struct pa_context *c, void *userdata) {
assert(c);
+ switch (pa_context_get_state(c)) {
+ case PA_CONTEXT_CONNECTING:
+ case PA_CONTEXT_AUTHORIZING:
+ case PA_CONTEXT_SETTING_NAME:
+ break;
+
+ case PA_CONTEXT_READY:
+ if (action == STAT)
+ pa_operation_unref(pa_context_stat(c, stat_callback, NULL));
+ else if (action == PLAY_SAMPLE)
+ pa_operation_unref(pa_context_play_sample(c, process_argv[2], NULL, 0x100, play_sample_callback, NULL));
+ else if (action == REMOVE_SAMPLE)
+ pa_operation_unref(pa_context_remove_sample(c, process_argv[2], remove_sample_callback, NULL));
+ else if (action == UPLOAD_SAMPLE) {
+
+ sample_stream = pa_stream_new(c, sample_name, &sample_spec);
+ assert(sample_stream);
+
+ pa_stream_set_state_callback(sample_stream, stream_state_callback, NULL);
+ pa_stream_set_write_callback(sample_stream, stream_write_callback, NULL);
+ pa_stream_connect_upload(sample_stream, sample_length);
+ } else {
+ assert(action == EXIT);
+ pa_context_exit_daemon(c);
+ drain();
+ }
+ break;
- if (!success) {
- fprintf(stderr, "Connection failed: %s\n", pa_strerror(pa_context_errno(c)));
- goto fail;
- }
+ case PA_CONTEXT_TERMINATED:
+ quit(0);
+ break;
- fprintf(stderr, "Connection established.\n");
-
- if (action == STAT)
- pa_context_stat(c, stat_callback, NULL);
- else if (action == PLAY_SAMPLE)
- pa_context_play_sample(c, process_argv[2], NULL, 0x100, play_sample_callback, NULL);
- else if (action == REMOVE_SAMPLE)
- pa_context_remove_sample(c, process_argv[2], remove_sample_callback, NULL);
- else if (action == UPLOAD_SAMPLE) {
- if (!(sample_stream = pa_context_upload_sample(c, sample_name, &sample_spec, sample_length, upload_callback, NULL))) {
- fprintf(stderr, "Failed to upload sample: %s\n", pa_strerror(pa_context_errno(c)));
- goto fail;
- }
-
- pa_stream_set_die_callback(sample_stream, stream_die_callback, NULL);
- pa_stream_set_write_callback(sample_stream, stream_write_callback, NULL);
- } else {
- assert(action == EXIT);
- pa_context_exit(c);
- drain();
+ case PA_CONTEXT_FAILED:
+ default:
+ fprintf(stderr, "Connection failure: %s\n", pa_strerror(pa_context_errno(c)));
+ quit(1);
}
-
- return;
-
-fail:
- quit(1);
}
static void exit_signal_callback(struct pa_mainloop_api *m, struct pa_signal_event *e, int sig, void *userdata) {
@@ -234,12 +228,15 @@ int main(int argc, char *argv[]) {
sample_name = argv[3];
else {
char *f = strrchr(argv[2], '/');
+ size_t n;
if (f)
f++;
else
f = argv[2];
- strncpy(sample_name = tmp, f, strcspn(f, "."));
+ n = strcspn(f, ".");
+ strncpy(sample_name = tmp, f, n);
+ tmp[n] = 0;
}
memset(&sfinfo, 0, sizeof(sfinfo));
@@ -292,12 +289,8 @@ int main(int argc, char *argv[]) {
goto quit;
}
- if (pa_context_connect(context, NULL, context_complete_callback, NULL) < 0) {
- fprintf(stderr, "pa_context_connext() failed.\n");
- goto quit;
- }
-
- pa_context_set_die_callback(context, context_die_callback, NULL);
+ pa_context_set_state_callback(context, context_state_callback, NULL);
+ pa_context_connect(context, NULL);
if (pa_mainloop_run(m, &ret) < 0) {
fprintf(stderr, "pa_mainloop_run() failed.\n");
@@ -305,8 +298,11 @@ int main(int argc, char *argv[]) {
}
quit:
+ if (sample_stream)
+ pa_stream_unref(sample_stream);
+
if (context)
- pa_context_free(context);
+ pa_context_unref(context);
if (m) {
pa_signal_done();
@@ -315,6 +311,6 @@ quit:
if (sndfile)
sf_close(sndfile);
-
+
return ret;
}
diff --git a/polyp/polyplib-context.c b/polyp/polyplib-context.c
index 35001d3d..5f849e24 100644
--- a/polyp/polyplib-context.c
+++ b/polyp/polyplib-context.c
@@ -31,7 +31,8 @@
#include <sys/socket.h>
#include <netdb.h>
-#include "polyplib.h"
+#include "polyplib-internal.h"
+#include "polyplib-context.h"
#include "native-common.h"
#include "pdispatch.h"
#include "pstream.h"
@@ -42,128 +43,11 @@
#include "util.h"
#include "xmalloc.h"
-#define DEFAULT_MAXLENGTH 204800
-#define DEFAULT_TLENGTH 10240
-#define DEFAULT_PREBUF 4096
-#define DEFAULT_MINREQ 1024
-#define DEFAULT_FRAGSIZE 1024
-
-#define DEFAULT_TIMEOUT (5*60)
-#define DEFAULT_SERVER "/tmp/polypaudio/native"
-#define DEFAULT_PORT "4713"
-
-struct pa_context {
- char *name;
- struct pa_mainloop_api* mainloop;
- struct pa_socket_client *client;
- struct pa_pstream *pstream;
- struct pa_pdispatch *pdispatch;
- struct pa_dynarray *record_streams, *playback_streams;
- struct pa_stream *first_stream;
- uint32_t ctag;
- uint32_t error;
- enum {
- CONTEXT_UNCONNECTED,
- CONTEXT_CONNECTING,
- CONTEXT_AUTHORIZING,
- CONTEXT_SETTING_NAME,
- CONTEXT_READY,
- CONTEXT_DEAD
- } state;
-
- void (*connect_complete_callback)(struct pa_context*c, int success, void *userdata);
- void *connect_complete_userdata;
-
- void (*drain_complete_callback)(struct pa_context*c, void *userdata);
- void *drain_complete_userdata;
-
- void (*die_callback)(struct pa_context*c, void *userdata);
- void *die_userdata;
-
- void (*stat_callback)(struct pa_context*c, uint32_t count, uint32_t total, void *userdata);
- void *stat_userdata;
-
- void (*play_sample_callback)(struct pa_context*c, int success, void *userdata);
- void *play_sample_userdata;
-
- void (*remove_sample_callback)(struct pa_context*c, int success, void *userdata);
- void *remove_sample_userdata;
-
- void (*get_server_info_callback)(struct pa_context*c, const struct pa_server_info* i, void *userdata);
- void *get_server_info_userdata;
-
- void (*get_sink_info_callback)(struct pa_context*c, const struct pa_sink_info* i, int is_last, void *userdata);
- void *get_sink_info_userdata;
-
- void (*get_source_info_callback)(struct pa_context*c, const struct pa_source_info* i, int is_last, void *userdata);
- void *get_source_info_userdata;
-
- void (*subscribe_callback)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata);
- void *subscribe_userdata;
- enum pa_subscription_mask subscribe_mask;
-
- void (*get_client_info_callback)(struct pa_context*c, const struct pa_client_info* i, int is_last, void *userdata);
- void *get_client_info_userdata;
-
- void (*get_module_info_callback)(struct pa_context*c, const struct pa_module_info* i, int is_last, void *userdata);
- void *get_module_info_userdata;
-
- uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH];
-};
-
-struct pa_stream {
- struct pa_context *context;
- struct pa_stream *next, *previous;
-
- char *name;
- struct pa_buffer_attr buffer_attr;
- struct pa_sample_spec sample_spec;
- uint32_t channel;
- int channel_valid;
- uint32_t device_index;
- enum pa_stream_direction direction;
-
- enum { STREAM_CREATING, STREAM_READY, STREAM_DEAD} state;
- uint32_t requested_bytes;
-
- void (*read_callback)(struct pa_stream *p, const void*data, size_t length, void *userdata);
- void *read_userdata;
-
- void (*write_callback)(struct pa_stream *p, size_t length, void *userdata);
- void *write_userdata;
-
- void (*create_complete_callback)(struct pa_stream *s, int success, void *userdata);
- void *create_complete_userdata;
-
- void (*drain_complete_callback)(struct pa_stream *s, void *userdata);
- void *drain_complete_userdata;
-
- void (*die_callback)(struct pa_stream*c, void *userdata);
- void *die_userdata;
-
- void (*get_latency_callback)(struct pa_stream*c, uint32_t latency, void *userdata);
- void *get_latency_userdata;
-
- void (*finish_sample_callback)(struct pa_stream*c, int success, void *userdata);
- void *finish_sample_userdata;
-};
-
-static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-
static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = {
- [PA_COMMAND_ERROR] = { NULL },
- [PA_COMMAND_REPLY] = { NULL },
- [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { NULL },
- [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { NULL },
- [PA_COMMAND_CREATE_RECORD_STREAM] = { NULL },
- [PA_COMMAND_DELETE_RECORD_STREAM] = { NULL },
- [PA_COMMAND_EXIT] = { NULL },
- [PA_COMMAND_REQUEST] = { command_request },
- [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { command_playback_stream_killed },
- [PA_COMMAND_RECORD_STREAM_KILLED] = { command_playback_stream_killed },
- [PA_COMMAND_SUBSCRIBE_EVENT] = { command_subscribe_event },
+ [PA_COMMAND_REQUEST] = { pa_command_request },
+ [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { pa_command_stream_killed },
+ [PA_COMMAND_RECORD_STREAM_KILLED] = { pa_command_stream_killed },
+ [PA_COMMAND_SUBSCRIBE_EVENT] = { pa_command_subscribe_event },
};
struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) {
@@ -171,65 +55,41 @@ struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *
assert(mainloop && name);
c = pa_xmalloc(sizeof(struct pa_context));
+ c->ref = 1;
c->name = pa_xstrdup(name);
c->mainloop = mainloop;
c->client = NULL;
c->pstream = NULL;
c->pdispatch = NULL;
c->playback_streams = pa_dynarray_new();
- assert(c->playback_streams);
c->record_streams = pa_dynarray_new();
- assert(c->record_streams);
- c->first_stream = NULL;
+ assert(c->playback_streams && c->record_streams);
+
+ PA_LLIST_HEAD_INIT(struct pa_stream, c->streams);
+ PA_LLIST_HEAD_INIT(struct pa_operation, c->operations);
+
c->error = PA_ERROR_OK;
- c->state = CONTEXT_UNCONNECTED;
+ c->state = PA_CONTEXT_UNCONNECTED;
c->ctag = 0;
- c->connect_complete_callback = NULL;
- c->connect_complete_userdata = NULL;
-
- c->drain_complete_callback = NULL;
- c->drain_complete_userdata = NULL;
-
- c->die_callback = NULL;
- c->die_userdata = NULL;
-
- c->stat_callback = NULL;
- c->stat_userdata = NULL;
-
- c->play_sample_callback = NULL;
- c->play_sample_userdata = NULL;
-
- c->remove_sample_callback = NULL;
- c->remove_sample_userdata = NULL;
-
- c->get_server_info_callback = NULL;
- c->get_server_info_userdata = NULL;
-
- c->get_sink_info_callback = NULL;
- c->get_sink_info_userdata = NULL;
-
- c->get_source_info_callback = NULL;
- c->get_source_info_userdata = NULL;
+ c->state_callback = NULL;
+ c->state_userdata = NULL;
c->subscribe_callback = NULL;
c->subscribe_userdata = NULL;
- c->get_client_info_callback = NULL;
- c->get_client_info_userdata = NULL;
-
- c->get_module_info_callback = NULL;
- c->get_module_info_userdata = NULL;
-
pa_check_for_sigpipe();
return c;
}
-void pa_context_free(struct pa_context *c) {
+static void context_free(struct pa_context *c) {
assert(c);
- while (c->first_stream)
- pa_stream_free(c->first_stream);
+ while (c->operations)
+ pa_operation_cancel(c->operations);
+
+ while (c->streams)
+ pa_stream_set_state(c->streams, PA_STREAM_TERMINATED);
if (c->client)
pa_socket_client_free(c->client);
@@ -237,6 +97,7 @@ void pa_context_free(struct pa_context *c) {
pa_pdispatch_free(c->pdispatch);
if (c->pstream)
pa_pstream_free(c->pstream);
+
if (c->record_streams)
pa_dynarray_free(c->record_streams, NULL, NULL);
if (c->playback_streams)
@@ -246,66 +107,82 @@ void pa_context_free(struct pa_context *c) {
pa_xfree(c);
}
-static void stream_dead(struct pa_stream *s) {
- assert(s);
-
- if (s->state == STREAM_DEAD)
- return;
-
- if (s->state == STREAM_READY) {
- s->state = STREAM_DEAD;
- if (s->die_callback)
- s->die_callback(s, s->die_userdata);
- } else
- s->state = STREAM_DEAD;
+struct pa_context* pa_context_ref(struct pa_context *c) {
+ assert(c && c->ref >= 1);
+ c->ref++;
+ return c;
}
-static void context_dead(struct pa_context *c) {
- struct pa_stream *s;
+void pa_context_unref(struct pa_context *c) {
+ assert(c && c->ref >= 1);
+
+ if ((--(c->ref)) == 0)
+ context_free(c);
+}
+
+void pa_context_set_state(struct pa_context *c, enum pa_context_state st) {
assert(c);
- if (c->state == CONTEXT_DEAD)
+ if (c->state == st)
return;
- if (c->pdispatch)
- pa_pdispatch_free(c->pdispatch);
- c->pdispatch = NULL;
-
- if (c->pstream)
- pa_pstream_free(c->pstream);
- c->pstream = NULL;
+ pa_context_ref(c);
+
+ if (st == PA_CONTEXT_FAILED || st == PA_CONTEXT_TERMINATED) {
+ struct pa_stream *s;
+
+ s = c->streams ? pa_stream_ref(c->streams) : NULL;
+ while (s) {
+ struct pa_stream *n = s->next ? pa_stream_ref(s->next) : NULL;
+ pa_stream_set_state(s, st == PA_CONTEXT_FAILED ? PA_STREAM_FAILED : PA_STREAM_TERMINATED);
+ pa_stream_unref(s);
+ s = n;
+ }
+
+ if (c->pdispatch)
+ pa_pdispatch_free(c->pdispatch);
+ c->pdispatch = NULL;
- if (c->client)
- pa_socket_client_free(c->client);
- c->client = NULL;
+ if (c->pstream)
+ pa_pstream_free(c->pstream);
+ c->pstream = NULL;
- for (s = c->first_stream; s; s = s->next)
- stream_dead(s);
-
- if (c->state == CONTEXT_READY) {
- c->state = CONTEXT_DEAD;
- if (c->die_callback)
- c->die_callback(c, c->die_userdata);
- } else
- c->state = CONTEXT_DEAD;
+ if (c->client)
+ pa_socket_client_free(c->client);
+ c->client = NULL;
+ }
+
+ c->state = st;
+ if (c->state_callback)
+ c->state_callback(c, c->state_userdata);
+
+ pa_context_unref(c);
+}
+
+void pa_context_fail(struct pa_context *c, int error) {
+ assert(c);
+ c->error = error;
+ pa_context_set_state(c, PA_CONTEXT_FAILED);
}
static void pstream_die_callback(struct pa_pstream *p, void *userdata) {
struct pa_context *c = userdata;
assert(p && c);
- c->error = PA_ERROR_CONNECTIONTERMINATED;
- context_dead(c);
+ pa_context_fail(c, PA_ERROR_CONNECTIONTERMINATED);
}
static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) {
struct pa_context *c = userdata;
assert(p && packet && c);
+ pa_context_ref(c);
+
if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) {
fprintf(stderr, "polyp.c: invalid packet.\n");
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
+ pa_context_fail(c, PA_ERROR_PROTOCOL);
}
+
+ pa_context_unref(c);
}
static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata) {
@@ -313,90 +190,100 @@ static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, in
struct pa_stream *s;
assert(p && chunk && c && chunk->memblock && chunk->memblock->data);
- if (!(s = pa_dynarray_get(c->record_streams, channel)))
- return;
+ pa_context_ref(c);
+
+ if ((s = pa_dynarray_get(c->record_streams, channel))) {
+ if (s->read_callback)
+ s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata);
+ }
- if (s->read_callback)
- s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata);
+ pa_context_unref(c);
}
-static int handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t) {
+int pa_context_handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t) {
assert(c && t);
-
+
if (command == PA_COMMAND_ERROR) {
if (pa_tagstruct_getu32(t, &c->error) < 0) {
- c->error = PA_ERROR_PROTOCOL;
+ pa_context_fail(c, PA_ERROR_PROTOCOL);
return -1;
+
}
-
- return 0;
+ } else if (command == PA_COMMAND_TIMEOUT)
+ c->error = PA_ERROR_TIMEOUT;
+ else {
+ pa_context_fail(c, PA_ERROR_PROTOCOL);
+ return -1;
}
- c->error = (command == PA_COMMAND_TIMEOUT) ? PA_ERROR_TIMEOUT : PA_ERROR_INTERNAL;
- return -1;
+ return 0;
}
static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
struct pa_context *c = userdata;
- assert(pd && c && (c->state == CONTEXT_AUTHORIZING || c->state == CONTEXT_SETTING_NAME));
+ assert(pd && c && (c->state == PA_CONTEXT_AUTHORIZING || c->state == PA_CONTEXT_SETTING_NAME));
+ pa_context_ref(c);
+
if (command != PA_COMMAND_REPLY) {
- handle_error(c, command, t);
- context_dead(c);
+ if (pa_context_handle_error(c, command, t) < 0)
+ pa_context_fail(c, PA_ERROR_PROTOCOL);
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 0, c->connect_complete_userdata);
-
- return;
+ goto finish;
}
- if (c->state == CONTEXT_AUTHORIZING) {
- struct pa_tagstruct *t;
- c->state = CONTEXT_SETTING_NAME;
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_SET_NAME);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, c->name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c);
- } else {
- assert(c->state == CONTEXT_SETTING_NAME);
-
- c->state = CONTEXT_READY;
+ switch(c->state) {
+ case PA_CONTEXT_AUTHORIZING: {
+ struct pa_tagstruct *t;
+ t = pa_tagstruct_new(NULL, 0);
+ assert(t);
+ pa_tagstruct_putu32(t, PA_COMMAND_SET_NAME);
+ pa_tagstruct_putu32(t, tag = c->ctag++);
+ pa_tagstruct_puts(t, c->name);
+ pa_pstream_send_tagstruct(c->pstream, t);
+ pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c);
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 1, c->connect_complete_userdata);
+ pa_context_set_state(c, PA_CONTEXT_SETTING_NAME);
+ break;
+ }
+
+ case PA_CONTEXT_SETTING_NAME :
+ pa_context_set_state(c, PA_CONTEXT_READY);
+ break;
+
+ default:
+ assert(0);
}
- return;
+finish:
+ pa_context_unref(c);
}
static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) {
struct pa_context *c = userdata;
struct pa_tagstruct *t;
uint32_t tag;
- assert(client && c && c->state == CONTEXT_CONNECTING);
+ assert(client && c && c->state == PA_CONTEXT_CONNECTING);
+ pa_context_ref(c);
+
pa_socket_client_free(client);
c->client = NULL;
if (!io) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- context_dead(c);
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 0, c->connect_complete_userdata);
-
- return;
+ pa_context_fail(c, PA_ERROR_CONNECTIONREFUSED);
+ goto finish;
}
-
+
+ assert(!c->pstream);
c->pstream = pa_pstream_new(c->mainloop, io);
assert(c->pstream);
+
pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c);
pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c);
pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c);
-
+
+ assert(!c->pdispatch);
c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX);
assert(c->pdispatch);
@@ -407,7 +294,11 @@ static void on_connection(struct pa_socket_client *client, struct pa_iochannel*i
pa_tagstruct_put_arbitrary(t, c->auth_cookie, sizeof(c->auth_cookie));
pa_pstream_send_tagstruct(c->pstream, t);
pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c);
- c->state = CONTEXT_AUTHORIZING;
+
+ pa_context_set_state(c, PA_CONTEXT_AUTHORIZING);
+
+finish:
+ pa_context_unref(c);
}
static struct sockaddr *resolve_server(const char *server, size_t *len) {
@@ -438,353 +329,89 @@ static struct sockaddr *resolve_server(const char *server, size_t *len) {
return sa;
}
-int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata) {
- assert(c && c->state == CONTEXT_UNCONNECTED);
+int pa_context_connect(struct pa_context *c, const char *server) {
+ int r = -1;
+ assert(c && c->ref >= 1 && c->state == PA_CONTEXT_UNCONNECTED);
+ pa_context_ref(c);
+
if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE, c->auth_cookie, sizeof(c->auth_cookie)) < 0) {
- c->error = PA_ERROR_AUTHKEY;
- return -1;
+ pa_context_fail(c, PA_ERROR_AUTHKEY);
+ goto finish;
}
if (!server)
- if (!(server = getenv("POLYP_SERVER")))
+ if (!(server = getenv(ENV_DEFAULT_SERVER)))
server = DEFAULT_SERVER;
assert(!c->client);
if (*server == '/') {
if (!(c->client = pa_socket_client_new_unix(c->mainloop, server))) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- return -1;
+ pa_context_fail(c, PA_ERROR_CONNECTIONREFUSED);
+ goto finish;
}
} else {
struct sockaddr* sa;
size_t sa_len;
if (!(sa = resolve_server(server, &sa_len))) {
- c->error = PA_ERROR_INVALIDSERVER;
- return -1;
+ pa_context_fail(c, PA_ERROR_INVALIDSERVER);
+ goto finish;
}
c->client = pa_socket_client_new_sockaddr(c->mainloop, sa, sa_len);
pa_xfree(sa);
if (!c->client) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- return -1;
+ pa_context_fail(c, PA_ERROR_CONNECTIONREFUSED);
+ goto finish;
}
}
- c->connect_complete_callback = complete;
- c->connect_complete_userdata = userdata;
-
pa_socket_client_set_callback(c->client, on_connection, c);
- c->state = CONTEXT_CONNECTING;
+ pa_context_set_state(c, PA_CONTEXT_CONNECTING);
- return 0;
+ r = 0;
+
+finish:
+ pa_context_unref(c);
+
+ return r;
}
-int pa_context_is_dead(struct pa_context *c) {
+void pa_context_disconnect(struct pa_context *c) {
assert(c);
- return c->state == CONTEXT_DEAD;
+ pa_context_set_state(c, PA_CONTEXT_TERMINATED);
}
-int pa_context_is_ready(struct pa_context *c) {
- assert(c);
- return c->state == CONTEXT_READY;
+enum pa_context_state pa_context_get_state(struct pa_context *c) {
+ assert(c && c->ref >= 1);
+ return c->state;
}
int pa_context_errno(struct pa_context *c) {
- assert(c);
+ assert(c && c->ref >= 1);
return c->error;
}
-void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata) {
- assert(c);
- c->die_callback = cb;
- c->die_userdata = userdata;
-}
-
-static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_stream *s;
- uint32_t channel;
- assert(pd && (command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED) && t && c);
-
- if (pa_tagstruct_getu32(t, &channel) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel)))
- return;
-
- c->error = PA_ERROR_KILLED;
- stream_dead(s);
-}
-
-static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s;
- struct pa_context *c = userdata;
- uint32_t bytes, channel;
- assert(pd && command == PA_COMMAND_REQUEST && t && c);
-
- if (pa_tagstruct_getu32(t, &channel) < 0 ||
- pa_tagstruct_getu32(t, &bytes) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (!(s = pa_dynarray_get(c->playback_streams, channel)))
- return;
-
- if (s->state != STREAM_READY)
- return;
-
- s->requested_bytes += bytes;
-
- if (s->requested_bytes && s->write_callback)
- s->write_callback(s, s->requested_bytes, s->write_userdata);
-}
-
-static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s && s->state == STREAM_CREATING);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- stream_dead(s);
- if (s->create_complete_callback)
- s->create_complete_callback(s, 0, s->create_complete_userdata);
-
- return;
- }
-
- if (pa_tagstruct_getu32(t, &s->channel) < 0 ||
- ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) ||
- !pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- s->channel_valid = 1;
- pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s);
-
- s->state = STREAM_READY;
- if (s->create_complete_callback)
- s->create_complete_callback(s, 1, s->create_complete_userdata);
-}
-
-static void create_stream(struct pa_stream *s, const char *dev) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(s);
-
- s->state = STREAM_CREATING;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM);
- pa_tagstruct_putu32(t, tag = s->context->ctag++);
- pa_tagstruct_puts(t, s->name);
- pa_tagstruct_put_sample_spec(t, &s->sample_spec);
- pa_tagstruct_putu32(t, (uint32_t) -1);
- pa_tagstruct_puts(t, dev ? dev : "");
- pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
- if (s->direction == PA_STREAM_PLAYBACK) {
- pa_tagstruct_putu32(t, s->buffer_attr.tlength);
- pa_tagstruct_putu32(t, s->buffer_attr.prebuf);
- pa_tagstruct_putu32(t, s->buffer_attr.minreq);
- } else
- pa_tagstruct_putu32(t, s->buffer_attr.fragsize);
-
- pa_pstream_send_tagstruct(s->context->pstream, t);
- pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s);
-}
-
-static struct pa_stream *internal_stream_new(struct pa_context *c) {
- struct pa_stream *s;
-
- s = pa_xmalloc(sizeof(struct pa_stream));
- s->context = c;
-
- s->read_callback = NULL;
- s->read_userdata = NULL;
- s->write_callback = NULL;
- s->write_userdata = NULL;
- s->die_callback = NULL;
- s->die_userdata = NULL;
- s->create_complete_callback = NULL;
- s->create_complete_userdata = NULL;
- s->get_latency_callback = NULL;
- s->get_latency_userdata = NULL;
- s->finish_sample_callback = NULL;
- s->finish_sample_userdata = NULL;
-
- s->name = NULL;
- s->state = STREAM_CREATING;
- s->requested_bytes = 0;
- s->channel = 0;
- s->channel_valid = 0;
- s->device_index = (uint32_t) -1;
-
- memset(&s->buffer_attr, 0, sizeof(s->buffer_attr));
-
- s->next = c->first_stream;
- if (s->next)
- s->next->previous = s;
- s->previous = NULL;
- c->first_stream = s;
-
- return s;
-}
-
-struct pa_stream* pa_stream_new(
- struct pa_context *c,
- enum pa_stream_direction dir,
- const char *dev,
- const char *name,
- const struct pa_sample_spec *ss,
- const struct pa_buffer_attr *attr,
- void (*complete) (struct pa_stream*s, int success, void *userdata),
- void *userdata) {
-
- struct pa_stream *s;
-
- assert(c && name && ss && c->state == CONTEXT_READY && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD));
-
- s = internal_stream_new(c);
- assert(s);
-
- s->create_complete_callback = complete;
- s->create_complete_userdata = userdata;
- s->name = pa_xstrdup(name);
- s->state = STREAM_CREATING;
- s->direction = dir;
- s->sample_spec = *ss;
- if (attr)
- s->buffer_attr = *attr;
- else {
- s->buffer_attr.maxlength = DEFAULT_MAXLENGTH;
- s->buffer_attr.tlength = DEFAULT_TLENGTH;
- s->buffer_attr.prebuf = DEFAULT_PREBUF;
- s->buffer_attr.minreq = DEFAULT_MINREQ;
- s->buffer_attr.fragsize = DEFAULT_FRAGSIZE;
- }
-
- create_stream(s, dev);
-
- return s;
-}
-
-void pa_stream_free(struct pa_stream *s) {
- assert(s && s->context);
-
- if (s->context->pdispatch)
- pa_pdispatch_unregister_reply(s->context->pdispatch, s);
-
- pa_xfree(s->name);
-
- if (s->channel_valid && s->context->state == CONTEXT_READY) {
- struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM :
- (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM));
- pa_tagstruct_putu32(t, s->context->ctag++);
- pa_tagstruct_putu32(t, s->channel);
- pa_pstream_send_tagstruct(s->context->pstream, t);
- }
-
- if (s->channel_valid)
- pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL);
-
- if (s->next)
- s->next->previous = s->previous;
- if (s->previous)
- s->previous->next = s->next;
- else
- s->context->first_stream = s->next;
-
- pa_xfree(s);
-}
-
-void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) {
- s->write_callback = cb;
- s->write_userdata = userdata;
-}
-
-void pa_stream_write(struct pa_stream *s, const void *data, size_t length) {
- struct pa_memchunk chunk;
- assert(s && s->context && data && length && s->state == STREAM_READY);
-
- chunk.memblock = pa_memblock_new(length);
- assert(chunk.memblock && chunk.memblock->data);
- memcpy(chunk.memblock->data, data, length);
- chunk.index = 0;
- chunk.length = length;
-
- pa_pstream_send_memblock(s->context->pstream, s->channel, 0, &chunk);
- pa_memblock_unref(chunk.memblock);
-
- /*fprintf(stderr, "Sent %u bytes\n", length);*/
-
- if (length < s->requested_bytes)
- s->requested_bytes -= length;
- else
- s->requested_bytes = 0;
-}
-
-size_t pa_stream_writable_size(struct pa_stream *s) {
- assert(s && s->state == STREAM_READY);
- return s->requested_bytes;
-}
-
-void pa_stream_set_read_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) {
- assert(s && cb);
- s->read_callback = cb;
- s->read_userdata = userdata;
-}
-
-int pa_stream_is_dead(struct pa_stream *s) {
- return s->state == STREAM_DEAD;
-}
-
-int pa_stream_is_ready(struct pa_stream*s) {
- return s->state == STREAM_READY;
-}
-
-void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata) {
- assert(s);
- s->die_callback = cb;
- s->die_userdata = userdata;
+void pa_context_set_state_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata) {
+ assert(c && c->ref >= 1);
+ c->state_callback = cb;
+ c->state_userdata = userdata;
}
int pa_context_is_pending(struct pa_context *c) {
- assert(c);
+ assert(c && c->ref >= 1);
- if (c->state != CONTEXT_READY)
+ if (c->state != PA_CONTEXT_READY)
return 0;
+ assert(c->pstream && c->pdispatch);
return pa_pstream_is_pending(c->pstream) || pa_pdispatch_is_pending(c->pdispatch);
}
-struct pa_context* pa_stream_get_context(struct pa_stream *p) {
- assert(p);
- return p->context;
-}
-
-static void set_dispatch_callbacks(struct pa_context *c);
+static void set_dispatch_callbacks(struct pa_operation *o);
static void pdispatch_drain_callback(struct pa_pdispatch*pd, void *userdata) {
set_dispatch_callbacks(userdata);
@@ -794,757 +421,106 @@ static void pstream_drain_callback(struct pa_pstream *s, void *userdata) {
set_dispatch_callbacks(userdata);
}
-static void set_dispatch_callbacks(struct pa_context *c) {
- assert(c && c->state == CONTEXT_READY);
-
- pa_pstream_set_drain_callback(c->pstream, NULL, NULL);
- pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL);
-
- if (pa_pdispatch_is_pending(c->pdispatch)) {
- pa_pdispatch_set_drain_callback(c->pdispatch, pdispatch_drain_callback, c);
- return;
- }
-
- if (pa_pstream_is_pending(c->pstream)) {
- pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c);
- return;
- }
-
- assert(c->drain_complete_callback);
- c->drain_complete_callback(c, c->drain_complete_userdata);
-}
-
-int pa_context_drain(
- struct pa_context *c,
- void (*complete) (struct pa_context*c, void *userdata),
- void *userdata) {
-
- assert(c && c->state == CONTEXT_READY);
-
- if (complete == NULL) {
- c->drain_complete_callback = NULL;
- pa_pstream_set_drain_callback(c->pstream, NULL, NULL);
- pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL);
- return 0;
- }
-
- if (!pa_context_is_pending(c))
- return -1;
-
- c->drain_complete_callback = complete;
- c->drain_complete_userdata = userdata;
-
- set_dispatch_callbacks(c);
-
- return 0;
-}
-
-static void stream_drain_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- stream_dead(s);
- return;
- }
-
- if (s->state != STREAM_READY)
- return;
-
- if (!pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->drain_complete_callback) {
- void (*temp) (struct pa_stream*s, void *userdata) = s->drain_complete_callback;
- s->drain_complete_callback = NULL;
- temp(s, s->drain_complete_userdata);
- }
-}
-
-
-void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(s && s->state == STREAM_READY);
-
- if (!complete) {
- s->drain_complete_callback = NULL;
- return;
- }
-
- s->drain_complete_callback = complete;
- s->drain_complete_userdata = userdata;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, PA_COMMAND_DRAIN_PLAYBACK_STREAM);
- pa_tagstruct_putu32(t, tag = s->context->ctag++);
- pa_tagstruct_putu32(t, s->channel);
- pa_pstream_send_tagstruct(s->context->pstream, t);
- pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_drain_callback, s);
-}
-
-void pa_context_exit(struct pa_context *c) {
- struct pa_tagstruct *t;
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_EXIT);
- pa_tagstruct_putu32(t, c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
-}
-
-static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- uint32_t total, count;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->stat_callback)
- c->stat_callback(c, (uint32_t) -1, (uint32_t) -1, c->stat_userdata);
- return;
- }
-
- if (pa_tagstruct_getu32(t, &count) < 0 ||
- pa_tagstruct_getu32(t, &total) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->stat_callback)
- c->stat_callback(c, count, total, c->stat_userdata);
-}
-
-void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata) {
- uint32_t tag;
- struct pa_tagstruct *t;
-
- c->stat_callback = cb;
- c->stat_userdata = userdata;
-
- if (cb == NULL)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_STAT);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_stat_callback, c);
-}
-
-static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- uint32_t latency;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- if (s->get_latency_callback)
- s->get_latency_callback(s, (uint32_t) -1, s->get_latency_userdata);
- return;
- }
-
- if (pa_tagstruct_getu32(t, &latency) < 0 ||
- !pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->get_latency_callback)
- s->get_latency_callback(s, latency, s->get_latency_userdata);
-}
-
-void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata) {
- uint32_t tag;
- struct pa_tagstruct *t;
-
- p->get_latency_callback = cb;
- p->get_latency_userdata = userdata;
-
- if (cb == NULL)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY);
- pa_tagstruct_putu32(t, tag = p->context->ctag++);
- pa_tagstruct_putu32(t, p->channel);
- pa_pstream_send_tagstruct(p->context->pstream, t);
- pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, p);
-}
-
-struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) {
- struct pa_stream *s;
- struct pa_tagstruct *t;
- uint32_t tag;
-
- s = internal_stream_new(c);
- assert(s);
-
- s->create_complete_callback = cb;
- s->create_complete_userdata = userdata;
- s->name = pa_xstrdup(name);
- s->state = STREAM_CREATING;
- s->direction = PA_STREAM_UPLOAD;
- s->sample_spec = *ss;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_CREATE_UPLOAD_STREAM);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, name);
- pa_tagstruct_put_sample_spec(t, ss);
- pa_tagstruct_putu32(t, length);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s);
-
- return s;
-}
-
-static void stream_finish_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- if (s->finish_sample_callback)
- s->finish_sample_callback(s, 0, s->finish_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->finish_sample_callback)
- s->finish_sample_callback(s, 1, s->finish_sample_userdata);
-}
+static void set_dispatch_callbacks(struct pa_operation *o) {
+ int done = 1;
+ assert(o && o->context && o->context->ref >= 1 && o->ref >= 1 && o->context->state == PA_CONTEXT_READY);
-void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(p);
-
- p->finish_sample_callback = cb;
- p->finish_sample_userdata = userdata;
+ pa_pstream_set_drain_callback(o->context->pstream, NULL, NULL);
+ pa_pdispatch_set_drain_callback(o->context->pdispatch, NULL, NULL);
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_FINISH_UPLOAD_STREAM);
- pa_tagstruct_putu32(t, tag = p->context->ctag++);
- pa_tagstruct_putu32(t, p->channel);
- pa_pstream_send_tagstruct(p->context->pstream, t);
- pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_finish_sample_callback, p);
-}
-
-static void context_play_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->play_sample_callback)
- c->play_sample_callback(c, 0, c->play_sample_userdata);
- return;
+ if (pa_pdispatch_is_pending(o->context->pdispatch)) {
+ pa_pdispatch_set_drain_callback(o->context->pdispatch, pdispatch_drain_callback, o);
+ done = 0;
}
- if (!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
+ if (pa_pstream_is_pending(o->context->pstream)) {
+ pa_pstream_set_drain_callback(o->context->pstream, pstream_drain_callback, o);
+ done = 0;
}
- if (c->play_sample_callback)
- c->play_sample_callback(c, 1, c->play_sample_userdata);
-}
-
-void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c && name && *name && (!dev || *dev));
-
- c->play_sample_callback = cb;
- c->play_sample_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_PLAY_SAMPLE);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, (uint32_t) -1);
- pa_tagstruct_puts(t, dev ? dev : "");
- pa_tagstruct_putu32(t, volume);
- pa_tagstruct_puts(t, name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_play_sample_callback, c);
-}
-
-static void context_remove_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->remove_sample_callback)
- c->remove_sample_callback(c, 0, c->remove_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->remove_sample_callback)
- c->remove_sample_callback(c, 1, c->remove_sample_userdata);
-}
-
-void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c && name);
-
- c->remove_sample_callback = cb;
- c->remove_sample_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_SAMPLE);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_remove_sample_callback, c);
-}
-
-static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_server_info i;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_server_info_callback)
- c->get_server_info_callback(c, NULL, c->get_server_info_userdata);
- return;
- }
-
- if (pa_tagstruct_gets(t, &i.server_name) < 0 ||
- pa_tagstruct_gets(t, &i.server_version) < 0 ||
- pa_tagstruct_gets(t, &i.user_name) < 0 ||
- pa_tagstruct_gets(t, &i.host_name) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_server_info_callback)
- c->get_server_info_callback(c, &i, c->get_server_info_userdata);
-}
-
-void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_server_info_callback = cb;
- c->get_server_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SERVER_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_server_info_callback, c);
-}
-
-static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, NULL, 0, c->get_sink_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_sink_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.description) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
- pa_tagstruct_getu32(t, &i.volume) < 0 ||
- pa_tagstruct_getu32(t, &i.monitor_source) < 0 ||
- pa_tagstruct_gets(t, &i.monitor_source_name) < 0 ||
- pa_tagstruct_getu32(t, &i.latency) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
+ if (!done)
+ pa_operation_ref(o);
+ else {
+ if (o->callback) {
+ void (*cb)(struct pa_context *c, void *userdata);
+ cb = (void*) o->callback;
+ cb(o->context, o->userdata);
}
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, &i, 0, c->get_sink_info_userdata);
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, NULL, 1, c->get_sink_info_userdata);
-}
-
-void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_sink_info_callback = cb;
- c->get_sink_info_userdata = userdata;
+ pa_operation_done(o);
+ }
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c);
+ pa_operation_unref(o);
}
-static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
+struct pa_operation* pa_context_drain(struct pa_context *c, void (*cb) (struct pa_context*c, void *userdata), void *userdata) {
+ struct pa_operation *o;
+ assert(c && c->ref >= 1 && c->state == PA_CONTEXT_READY);
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
+ if (!pa_context_is_pending(c))
+ return NULL;
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, NULL, 0, c->get_source_info_userdata);
- return;
- }
+ o = pa_operation_new(c, NULL);
+ assert(o);
+ o->callback = cb;
+ o->userdata = userdata;
- while (!pa_tagstruct_eof(t)) {
- struct pa_source_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.description) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
- pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 ||
- pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, &i, 0, c->get_source_info_userdata);
- }
+ set_dispatch_callbacks(pa_operation_ref(o));
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, NULL, 1, c->get_source_info_userdata);
+ return o;
}
-void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
+void pa_context_exit_daemon(struct pa_context *c) {
struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_source_info_callback = cb;
- c->get_source_info_userdata = userdata;
-
- if (!cb)
- return;
+ assert(c && c->ref >= 1);
t = pa_tagstruct_new(NULL, 0);
assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c);
-}
-
-void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- assert(c);
-
- c->subscribe_callback = cb;
- c->subscribe_userdata = userdata;
- c->subscribe_mask = m;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE);
+ pa_tagstruct_putu32(t, PA_COMMAND_EXIT);
pa_tagstruct_putu32(t, c->ctag++);
- pa_tagstruct_putu32(t, cb ? m : 0);
- pa_pstream_send_tagstruct(c->pstream, t);
-}
-
-static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- enum pa_subscription_event_type e;
- uint32_t index;
- assert(pd && command == PA_COMMAND_SUBSCRIBE_EVENT && t && c);
-
- if (pa_tagstruct_getu32(t, &e) < 0 ||
- pa_tagstruct_getu32(t, &index) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (pa_subscription_match_flags(c->subscribe_mask, e) && c->subscribe_callback)
- c->subscribe_callback(c, e, index, c->subscribe_userdata);
-}
-
-void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_sink_info_callback = cb;
- c->get_sink_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_tagstruct_puts(t, "");
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c);
-}
-
-void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_source_info_callback = cb;
- c->get_source_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_tagstruct_puts(t, "");
pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c);
}
-static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
+void pa_context_simple_ack_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
+ struct pa_operation *o = userdata;
+ int success = 1;
+ assert(pd && o && o->context && o->ref >= 1);
if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
+ if (pa_context_handle_error(o->context, command, t) < 0)
+ goto finish;
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, NULL, 0, c->get_client_info_userdata);
- return;
+ success = 0;
+ } else if (!pa_tagstruct_eof(t)) {
+ pa_context_fail(o->context, PA_ERROR_PROTOCOL);
+ goto finish;
}
- while (!pa_tagstruct_eof(t)) {
- struct pa_client_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.protocol_name) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, &i, 0, c->get_client_info_userdata);
+ if (o->callback) {
+ void (*cb)(struct pa_context *c, int success, void *userdata) = o->callback;
+ cb(o->context, success, o->userdata);
}
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, NULL, 1, c->get_client_info_userdata);
+finish:
+ pa_operation_done(o);
+ pa_operation_unref(o);
}
-
-void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
+struct pa_operation* pa_context_send_simple_command(struct pa_context *c, uint32_t command, void (*internal_callback)(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata), void (*cb)(), void *userdata) {
struct pa_tagstruct *t;
+ struct pa_operation *o;
uint32_t tag;
- assert(c);
+ assert(c && cb);
- c->get_client_info_callback = cb;
- c->get_client_info_userdata = userdata;
+ o = pa_operation_new(c, NULL);
+ o->callback = cb;
+ o->userdata = userdata;
- if (!cb)
- return;
-
t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO);
+ pa_tagstruct_putu32(t, command);
pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c);
-}
+ pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, internal_callback, o);
-void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_client_info_callback = cb;
- c->get_client_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c);
-}
-
-static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, NULL, 0, c->get_module_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_module_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.argument) < 0 ||
- pa_tagstruct_getu32(t, &i.n_used) < 0 ||
- pa_tagstruct_getu32(t, &i.auto_unload) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, &i, 0, c->get_module_info_userdata);
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, NULL, 1, c->get_module_info_userdata);
-}
-
-void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_module_info_callback = cb;
- c->get_module_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c);
-}
-
-void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_module_info_callback = cb;
- c->get_module_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c);
+ return pa_operation_ref(o);
}
diff --git a/polyp/polyplib-context.h b/polyp/polyplib-context.h
index a0dd9f9c..6a1cc8bd 100644
--- a/polyp/polyplib-context.h
+++ b/polyp/polyplib-context.h
@@ -1,5 +1,5 @@
-#ifndef foopolyplibhfoo
-#define foopolyplibhfoo
+#ifndef foopolyplibcontexthfoo
+#define foopolyplibcontexthfoo
/* $Id$ */
@@ -22,157 +22,71 @@
USA.
***/
-#include <sys/types.h>
-
#include "sample.h"
#include "polyplib-def.h"
#include "mainloop-api.h"
+#include "cdecl.h"
+#include "polyplib-operation.h"
+
+/** \file
+ * Connection contexts */
+
+PA_C_DECL_BEGIN
+
+/** The state of a connection context */
+enum pa_context_state {
+ PA_CONTEXT_UNCONNECTED, /**< The context hasn't been connected yet */
+ PA_CONTEXT_CONNECTING, /**< A connection is being established */
+ PA_CONTEXT_AUTHORIZING, /**< The client is authorizing itself to the daemon */
+ PA_CONTEXT_SETTING_NAME, /**< The client is passing its application name to the daemon */
+ PA_CONTEXT_READY, /**< The connection is established, the context is ready to execute operations */
+ PA_CONTEXT_FAILED, /**< The connection failed or was disconnected */
+ PA_CONTEXT_TERMINATED /**< The connect was terminated cleanly */
+};
-#ifdef __cplusplus
-//extern "C" {
-#endif
-
+/** \struct pa_context
+ * A connection context to a daemon */
struct pa_context;
-struct pa_stream;
+/** Instantiate a new connection context with an abstract mainloop API
+ * and an application name */
struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name);
+
+/** Decrease the reference counter of the context by one */
void pa_context_unref(struct pa_context *c);
+
+/** Increase the reference counter of the context by one */
struct pa_context* pa_context_ref(struct pa_context *c);
-int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata);
-int pa_context_drain(struct pa_context *c, void (*complete) (struct pa_context*c, void *userdata), void *userdata);
-void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata);
+/** Set a callback function that is called whenever the context status changes */
+void pa_context_set_state_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata);
-int pa_context_is_dead(struct pa_context *c);
-int pa_context_is_ready(struct pa_context *c);
+/** Return the error number of the last failed operation */
int pa_context_errno(struct pa_context *c);
+/** Return non-zero if some data is pending to be written to the connection */
int pa_context_is_pending(struct pa_context *c);
-struct pa_stream* pa_stream_new(struct pa_context *c, enum pa_stream_direction dir, const char *dev, const char *name, const struct pa_sample_spec *ss, const struct pa_buffer_attr *attr, void (*complete) (struct pa_stream*s, int success, void *userdata), void *userdata);
-void pa_stream_unref(struct pa_stream *s);
-struct pa_stream *pa_stream_ref(struct pa_stream *s);
-
-void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata);
-
-void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata);
-
-void pa_stream_set_write_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata);
-void pa_stream_write(struct pa_stream *p, const void *data, size_t length);
-size_t pa_stream_writable_size(struct pa_stream *p);
+/** Return the current context status */
+enum pa_context_state pa_context_get_state(struct pa_context *c);
-void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata);
+/** Connect the context to the specified server. If server is NULL,
+connect to the default server. This routine may but will not always
+return synchronously on error. Use pa_context_set_state_callback() to
+be notified when the connection is established */
+int pa_context_connect(struct pa_context *c, const char *server);
-int pa_stream_is_dead(struct pa_stream *p);
-int pa_stream_is_ready(struct pa_stream*p);
+/** Terminate the context connection immediately */
+void pa_context_disconnect(struct pa_context *c);
-void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata);
+/** Drain the context. If there is nothing to drain, the function returns NULL */
+struct pa_operation* pa_context_drain(struct pa_context *c, void (*cb) (struct pa_context*c, void *userdata), void *userdata);
-struct pa_context* pa_stream_get_context(struct pa_stream *p);
+/** Tell the daemon to exit. No operation object is returned as the
+ * connection is terminated when the daemon quits, thus this operation
+ * would never complete. */
+void pa_context_exit_daemon(struct pa_context *c);
-uint32_t pa_stream_get_index(struct pa_stream *s);
-
-struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata);
-void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata);
-
-void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-
-struct pa_sink_info {
- const char *name;
- uint32_t index;
- const char *description;
- struct pa_sample_spec sample_spec;
- uint32_t owner_module;
- uint32_t volume;
- uint32_t monitor_source;
- const char *monitor_source_name;
- uint32_t latency;
-};
-
-void pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-
-struct pa_source_info {
- const char *name;
- uint32_t index;
- const char *description;
- struct pa_sample_spec sample_spec;
- uint32_t owner_module;
- uint32_t monitor_of_sink;
- const char *monitor_of_sink_name;
-};
-
-void pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-
-struct pa_server_info {
- const char *user_name;
- const char *host_name;
- const char *server_version;
- const char *server_name;
- struct pa_sample_spec sample_spec;
-};
-
-void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata);
-
-struct pa_module_info {
- uint32_t index;
- const char*name, *argument;
- uint32_t n_used, auto_unload;
-};
-
-void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata);
-
-struct pa_client_info {
- uint32_t index;
- const char *name;
- uint32_t owner_module;
- const char *protocol_name;
-};
-
-void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata);
-
-struct pa_sink_input_info {
- uint32_t index;
- const char *name;
- uint32_t owner_module;
- uint32_t owner_client;
- uint32_t sink;
- struct pa_sample_spec sample_spec;
- uint32_t volume;
- uint32_t latency;
-};
-
-void pa_context_get_sink_input_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_input_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata);
-
-struct pa_source_output_info {
- uint32_t index;
- const char *name;
- uint32_t owner_module;
- uint32_t owner_client;
- uint32_t source;
- struct pa_sample_spec sample_spec;
-};
-
-void pa_context_get_source_output_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_output_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata);
-
-void pa_context_set_sink_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-void pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-
-void pa_context_exit(struct pa_context *c);
-void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata);
-
-void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata);
-
-#ifdef __cplusplus
-}
-#endif
+PA_C_DECL_END
#endif
diff --git a/polyp/polyplib-def.h b/polyp/polyplib-def.h
index d96c6899..fc19be69 100644
--- a/polyp/polyplib-def.h
+++ b/polyp/polyplib-def.h
@@ -23,14 +23,13 @@
***/
#include <inttypes.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#include "native-common.h"
+#include "cdecl.h"
+
+PA_C_DECL_BEGIN
enum pa_stream_direction {
+ PA_STREAM_NODIRECTION,
PA_STREAM_PLAYBACK,
PA_STREAM_RECORD,
PA_STREAM_UPLOAD
@@ -43,9 +42,9 @@ struct pa_buffer_attr {
uint32_t minreq;
uint32_t fragsize;
};
-
-#ifdef __cplusplus
-}
-#endif
+
+#define PA_INVALID_INDEX ((uint32_t) -1)
+
+PA_C_DECL_END
#endif
diff --git a/polyp/polyplib-error.h b/polyp/polyplib-error.h
index d76ce6ff..d7519af4 100644
--- a/polyp/polyplib-error.h
+++ b/polyp/polyplib-error.h
@@ -23,15 +23,13 @@
***/
#include <inttypes.h>
+#include "cdecl.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
+PA_C_DECL_BEGIN;
+/** Return a human readable error message for the specified numeric error code */
const char* pa_strerror(uint32_t error);
-#ifdef __cplusplus
-}
-#endif
-
+PA_C_DECL_END;
+
#endif
diff --git a/polyp/polyplib-internal.h b/polyp/polyplib-internal.h
index 35001d3d..0b6b3887 100644
--- a/polyp/polyplib-internal.h
+++ b/polyp/polyplib-internal.h
@@ -1,3 +1,6 @@
+#ifndef foopolyplibinternalhfoo
+#define foopolyplibinternalhfoo
+
/* $Id$ */
/***
@@ -19,28 +22,16 @@
USA.
***/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-
-#include "polyplib.h"
-#include "native-common.h"
-#include "pdispatch.h"
+#include "mainloop-api.h"
+#include "socket-client.h"
#include "pstream.h"
+#include "pdispatch.h"
#include "dynarray.h"
-#include "socket-client.h"
-#include "pstream-util.h"
-#include "authkey.h"
-#include "util.h"
-#include "xmalloc.h"
+
+#include "polyplib-context.h"
+#include "polyplib-stream.h"
+#include "polyplib-operation.h"
+#include "llist.h"
#define DEFAULT_MAXLENGTH 204800
#define DEFAULT_TLENGTH 10240
@@ -52,68 +43,41 @@
#define DEFAULT_SERVER "/tmp/polypaudio/native"
#define DEFAULT_PORT "4713"
+#define ENV_DEFAULT_SINK "POLYP_SINK"
+#define ENV_DEFAULT_SOURCE "POLYP_SOURCE"
+#define ENV_DEFAULT_SERVER "POLYP_SERVER"
+
struct pa_context {
+ int ref;
+
char *name;
struct pa_mainloop_api* mainloop;
+
struct pa_socket_client *client;
struct pa_pstream *pstream;
struct pa_pdispatch *pdispatch;
+
struct pa_dynarray *record_streams, *playback_streams;
- struct pa_stream *first_stream;
+ PA_LLIST_HEAD(struct pa_stream, streams);
+ PA_LLIST_HEAD(struct pa_operation, operations);
+
uint32_t ctag;
uint32_t error;
- enum {
- CONTEXT_UNCONNECTED,
- CONTEXT_CONNECTING,
- CONTEXT_AUTHORIZING,
- CONTEXT_SETTING_NAME,
- CONTEXT_READY,
- CONTEXT_DEAD
- } state;
-
- void (*connect_complete_callback)(struct pa_context*c, int success, void *userdata);
- void *connect_complete_userdata;
-
- void (*drain_complete_callback)(struct pa_context*c, void *userdata);
- void *drain_complete_userdata;
+ enum pa_context_state state;
- void (*die_callback)(struct pa_context*c, void *userdata);
- void *die_userdata;
-
- void (*stat_callback)(struct pa_context*c, uint32_t count, uint32_t total, void *userdata);
- void *stat_userdata;
-
- void (*play_sample_callback)(struct pa_context*c, int success, void *userdata);
- void *play_sample_userdata;
+ uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH];
- void (*remove_sample_callback)(struct pa_context*c, int success, void *userdata);
- void *remove_sample_userdata;
-
- void (*get_server_info_callback)(struct pa_context*c, const struct pa_server_info* i, void *userdata);
- void *get_server_info_userdata;
-
- void (*get_sink_info_callback)(struct pa_context*c, const struct pa_sink_info* i, int is_last, void *userdata);
- void *get_sink_info_userdata;
-
- void (*get_source_info_callback)(struct pa_context*c, const struct pa_source_info* i, int is_last, void *userdata);
- void *get_source_info_userdata;
+ void (*state_callback)(struct pa_context*c, void *userdata);
+ void *state_userdata;
void (*subscribe_callback)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata);
void *subscribe_userdata;
- enum pa_subscription_mask subscribe_mask;
-
- void (*get_client_info_callback)(struct pa_context*c, const struct pa_client_info* i, int is_last, void *userdata);
- void *get_client_info_userdata;
-
- void (*get_module_info_callback)(struct pa_context*c, const struct pa_module_info* i, int is_last, void *userdata);
- void *get_module_info_userdata;
-
- uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH];
};
struct pa_stream {
+ int ref;
struct pa_context *context;
- struct pa_stream *next, *previous;
+ PA_LLIST_FIELDS(struct pa_stream);
char *name;
struct pa_buffer_attr buffer_attr;
@@ -122,1429 +86,47 @@ struct pa_stream {
int channel_valid;
uint32_t device_index;
enum pa_stream_direction direction;
-
- enum { STREAM_CREATING, STREAM_READY, STREAM_DEAD} state;
uint32_t requested_bytes;
+ enum pa_stream_state state;
+
+ void (*state_callback)(struct pa_stream*c, void *userdata);
+ void *state_userdata;
void (*read_callback)(struct pa_stream *p, const void*data, size_t length, void *userdata);
void *read_userdata;
void (*write_callback)(struct pa_stream *p, size_t length, void *userdata);
void *write_userdata;
-
- void (*create_complete_callback)(struct pa_stream *s, int success, void *userdata);
- void *create_complete_userdata;
-
- void (*drain_complete_callback)(struct pa_stream *s, void *userdata);
- void *drain_complete_userdata;
-
- void (*die_callback)(struct pa_stream*c, void *userdata);
- void *die_userdata;
-
- void (*get_latency_callback)(struct pa_stream*c, uint32_t latency, void *userdata);
- void *get_latency_userdata;
-
- void (*finish_sample_callback)(struct pa_stream*c, int success, void *userdata);
- void *finish_sample_userdata;
};
-static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
+struct pa_operation {
+ int ref;
+ struct pa_context *context;
+ struct pa_stream *stream;
+ PA_LLIST_FIELDS(struct pa_operation);
-static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = {
- [PA_COMMAND_ERROR] = { NULL },
- [PA_COMMAND_REPLY] = { NULL },
- [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { NULL },
- [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { NULL },
- [PA_COMMAND_CREATE_RECORD_STREAM] = { NULL },
- [PA_COMMAND_DELETE_RECORD_STREAM] = { NULL },
- [PA_COMMAND_EXIT] = { NULL },
- [PA_COMMAND_REQUEST] = { command_request },
- [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { command_playback_stream_killed },
- [PA_COMMAND_RECORD_STREAM_KILLED] = { command_playback_stream_killed },
- [PA_COMMAND_SUBSCRIBE_EVENT] = { command_subscribe_event },
+ enum pa_operation_state state;
+ void *userdata;
+ void (*callback)();
};
-struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) {
- struct pa_context *c;
- assert(mainloop && name);
-
- c = pa_xmalloc(sizeof(struct pa_context));
- c->name = pa_xstrdup(name);
- c->mainloop = mainloop;
- c->client = NULL;
- c->pstream = NULL;
- c->pdispatch = NULL;
- c->playback_streams = pa_dynarray_new();
- assert(c->playback_streams);
- c->record_streams = pa_dynarray_new();
- assert(c->record_streams);
- c->first_stream = NULL;
- c->error = PA_ERROR_OK;
- c->state = CONTEXT_UNCONNECTED;
- c->ctag = 0;
-
- c->connect_complete_callback = NULL;
- c->connect_complete_userdata = NULL;
-
- c->drain_complete_callback = NULL;
- c->drain_complete_userdata = NULL;
-
- c->die_callback = NULL;
- c->die_userdata = NULL;
-
- c->stat_callback = NULL;
- c->stat_userdata = NULL;
-
- c->play_sample_callback = NULL;
- c->play_sample_userdata = NULL;
-
- c->remove_sample_callback = NULL;
- c->remove_sample_userdata = NULL;
-
- c->get_server_info_callback = NULL;
- c->get_server_info_userdata = NULL;
-
- c->get_sink_info_callback = NULL;
- c->get_sink_info_userdata = NULL;
-
- c->get_source_info_callback = NULL;
- c->get_source_info_userdata = NULL;
-
- c->subscribe_callback = NULL;
- c->subscribe_userdata = NULL;
-
- c->get_client_info_callback = NULL;
- c->get_client_info_userdata = NULL;
-
- c->get_module_info_callback = NULL;
- c->get_module_info_userdata = NULL;
-
- pa_check_for_sigpipe();
- return c;
-}
-
-void pa_context_free(struct pa_context *c) {
- assert(c);
-
- while (c->first_stream)
- pa_stream_free(c->first_stream);
-
- if (c->client)
- pa_socket_client_free(c->client);
- if (c->pdispatch)
- pa_pdispatch_free(c->pdispatch);
- if (c->pstream)
- pa_pstream_free(c->pstream);
- if (c->record_streams)
- pa_dynarray_free(c->record_streams, NULL, NULL);
- if (c->playback_streams)
- pa_dynarray_free(c->playback_streams, NULL, NULL);
-
- pa_xfree(c->name);
- pa_xfree(c);
-}
-
-static void stream_dead(struct pa_stream *s) {
- assert(s);
-
- if (s->state == STREAM_DEAD)
- return;
-
- if (s->state == STREAM_READY) {
- s->state = STREAM_DEAD;
- if (s->die_callback)
- s->die_callback(s, s->die_userdata);
- } else
- s->state = STREAM_DEAD;
-}
-
-static void context_dead(struct pa_context *c) {
- struct pa_stream *s;
- assert(c);
-
- if (c->state == CONTEXT_DEAD)
- return;
-
- if (c->pdispatch)
- pa_pdispatch_free(c->pdispatch);
- c->pdispatch = NULL;
-
- if (c->pstream)
- pa_pstream_free(c->pstream);
- c->pstream = NULL;
-
- if (c->client)
- pa_socket_client_free(c->client);
- c->client = NULL;
-
- for (s = c->first_stream; s; s = s->next)
- stream_dead(s);
-
- if (c->state == CONTEXT_READY) {
- c->state = CONTEXT_DEAD;
- if (c->die_callback)
- c->die_callback(c, c->die_userdata);
- } else
- c->state = CONTEXT_DEAD;
-}
-
-static void pstream_die_callback(struct pa_pstream *p, void *userdata) {
- struct pa_context *c = userdata;
- assert(p && c);
- c->error = PA_ERROR_CONNECTIONTERMINATED;
- context_dead(c);
-}
-
-static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) {
- struct pa_context *c = userdata;
- assert(p && packet && c);
-
- if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) {
- fprintf(stderr, "polyp.c: invalid packet.\n");
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- }
-}
-
-static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_stream *s;
- assert(p && chunk && c && chunk->memblock && chunk->memblock->data);
-
- if (!(s = pa_dynarray_get(c->record_streams, channel)))
- return;
-
- if (s->read_callback)
- s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata);
-}
-
-static int handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t) {
- assert(c && t);
-
- if (command == PA_COMMAND_ERROR) {
- if (pa_tagstruct_getu32(t, &c->error) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- return -1;
- }
-
- return 0;
- }
-
- c->error = (command == PA_COMMAND_TIMEOUT) ? PA_ERROR_TIMEOUT : PA_ERROR_INTERNAL;
- return -1;
-}
-
-static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c && (c->state == CONTEXT_AUTHORIZING || c->state == CONTEXT_SETTING_NAME));
-
- if (command != PA_COMMAND_REPLY) {
- handle_error(c, command, t);
- context_dead(c);
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 0, c->connect_complete_userdata);
-
- return;
- }
-
- if (c->state == CONTEXT_AUTHORIZING) {
- struct pa_tagstruct *t;
- c->state = CONTEXT_SETTING_NAME;
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_SET_NAME);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, c->name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c);
- } else {
- assert(c->state == CONTEXT_SETTING_NAME);
-
- c->state = CONTEXT_READY;
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 1, c->connect_complete_userdata);
- }
-
- return;
-}
-
-static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(client && c && c->state == CONTEXT_CONNECTING);
+void pa_command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
+void pa_command_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
+void pa_command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
- pa_socket_client_free(client);
- c->client = NULL;
+struct pa_operation *pa_operation_new(struct pa_context *c, struct pa_stream *s);
+void pa_operation_done(struct pa_operation *o);
- if (!io) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- context_dead(c);
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 0, c->connect_complete_userdata);
-
- return;
- }
-
- c->pstream = pa_pstream_new(c->mainloop, io);
- assert(c->pstream);
- pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c);
- pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c);
- pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c);
-
- c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX);
- assert(c->pdispatch);
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_AUTH);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_put_arbitrary(t, c->auth_cookie, sizeof(c->auth_cookie));
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c);
- c->state = CONTEXT_AUTHORIZING;
-}
-
-static struct sockaddr *resolve_server(const char *server, size_t *len) {
- struct sockaddr *sa;
- struct addrinfo hints, *result = NULL;
- char *port;
- assert(server && len);
-
- if ((port = strrchr(server, ':')))
- port++;
- if (!port)
- port = DEFAULT_PORT;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = 0;
-
- if (getaddrinfo(server, port, &hints, &result) != 0)
- return NULL;
- assert(result);
-
- sa = pa_xmalloc(*len = result->ai_addrlen);
- memcpy(sa, result->ai_addr, *len);
-
- freeaddrinfo(result);
-
- return sa;
-}
-
-int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata) {
- assert(c && c->state == CONTEXT_UNCONNECTED);
-
- if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE, c->auth_cookie, sizeof(c->auth_cookie)) < 0) {
- c->error = PA_ERROR_AUTHKEY;
- return -1;
- }
-
- if (!server)
- if (!(server = getenv("POLYP_SERVER")))
- server = DEFAULT_SERVER;
-
- assert(!c->client);
-
- if (*server == '/') {
- if (!(c->client = pa_socket_client_new_unix(c->mainloop, server))) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- return -1;
- }
- } else {
- struct sockaddr* sa;
- size_t sa_len;
-
- if (!(sa = resolve_server(server, &sa_len))) {
- c->error = PA_ERROR_INVALIDSERVER;
- return -1;
- }
-
- c->client = pa_socket_client_new_sockaddr(c->mainloop, sa, sa_len);
- pa_xfree(sa);
-
- if (!c->client) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- return -1;
- }
- }
-
- c->connect_complete_callback = complete;
- c->connect_complete_userdata = userdata;
-
- pa_socket_client_set_callback(c->client, on_connection, c);
- c->state = CONTEXT_CONNECTING;
-
- return 0;
-}
-
-int pa_context_is_dead(struct pa_context *c) {
- assert(c);
- return c->state == CONTEXT_DEAD;
-}
-
-int pa_context_is_ready(struct pa_context *c) {
- assert(c);
- return c->state == CONTEXT_READY;
-}
-
-int pa_context_errno(struct pa_context *c) {
- assert(c);
- return c->error;
-}
-
-void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata) {
- assert(c);
- c->die_callback = cb;
- c->die_userdata = userdata;
-}
-
-static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_stream *s;
- uint32_t channel;
- assert(pd && (command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED) && t && c);
-
- if (pa_tagstruct_getu32(t, &channel) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel)))
- return;
-
- c->error = PA_ERROR_KILLED;
- stream_dead(s);
-}
-
-static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s;
- struct pa_context *c = userdata;
- uint32_t bytes, channel;
- assert(pd && command == PA_COMMAND_REQUEST && t && c);
-
- if (pa_tagstruct_getu32(t, &channel) < 0 ||
- pa_tagstruct_getu32(t, &bytes) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (!(s = pa_dynarray_get(c->playback_streams, channel)))
- return;
-
- if (s->state != STREAM_READY)
- return;
-
- s->requested_bytes += bytes;
-
- if (s->requested_bytes && s->write_callback)
- s->write_callback(s, s->requested_bytes, s->write_userdata);
-}
-
-static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s && s->state == STREAM_CREATING);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- stream_dead(s);
- if (s->create_complete_callback)
- s->create_complete_callback(s, 0, s->create_complete_userdata);
-
- return;
- }
-
- if (pa_tagstruct_getu32(t, &s->channel) < 0 ||
- ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) ||
- !pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- s->channel_valid = 1;
- pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s);
-
- s->state = STREAM_READY;
- if (s->create_complete_callback)
- s->create_complete_callback(s, 1, s->create_complete_userdata);
-}
-
-static void create_stream(struct pa_stream *s, const char *dev) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(s);
-
- s->state = STREAM_CREATING;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM);
- pa_tagstruct_putu32(t, tag = s->context->ctag++);
- pa_tagstruct_puts(t, s->name);
- pa_tagstruct_put_sample_spec(t, &s->sample_spec);
- pa_tagstruct_putu32(t, (uint32_t) -1);
- pa_tagstruct_puts(t, dev ? dev : "");
- pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
- if (s->direction == PA_STREAM_PLAYBACK) {
- pa_tagstruct_putu32(t, s->buffer_attr.tlength);
- pa_tagstruct_putu32(t, s->buffer_attr.prebuf);
- pa_tagstruct_putu32(t, s->buffer_attr.minreq);
- } else
- pa_tagstruct_putu32(t, s->buffer_attr.fragsize);
-
- pa_pstream_send_tagstruct(s->context->pstream, t);
- pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s);
-}
-
-static struct pa_stream *internal_stream_new(struct pa_context *c) {
- struct pa_stream *s;
-
- s = pa_xmalloc(sizeof(struct pa_stream));
- s->context = c;
-
- s->read_callback = NULL;
- s->read_userdata = NULL;
- s->write_callback = NULL;
- s->write_userdata = NULL;
- s->die_callback = NULL;
- s->die_userdata = NULL;
- s->create_complete_callback = NULL;
- s->create_complete_userdata = NULL;
- s->get_latency_callback = NULL;
- s->get_latency_userdata = NULL;
- s->finish_sample_callback = NULL;
- s->finish_sample_userdata = NULL;
-
- s->name = NULL;
- s->state = STREAM_CREATING;
- s->requested_bytes = 0;
- s->channel = 0;
- s->channel_valid = 0;
- s->device_index = (uint32_t) -1;
-
- memset(&s->buffer_attr, 0, sizeof(s->buffer_attr));
-
- s->next = c->first_stream;
- if (s->next)
- s->next->previous = s;
- s->previous = NULL;
- c->first_stream = s;
-
- return s;
-}
-
-struct pa_stream* pa_stream_new(
- struct pa_context *c,
- enum pa_stream_direction dir,
- const char *dev,
- const char *name,
- const struct pa_sample_spec *ss,
- const struct pa_buffer_attr *attr,
- void (*complete) (struct pa_stream*s, int success, void *userdata),
- void *userdata) {
-
- struct pa_stream *s;
-
- assert(c && name && ss && c->state == CONTEXT_READY && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD));
-
- s = internal_stream_new(c);
- assert(s);
-
- s->create_complete_callback = complete;
- s->create_complete_userdata = userdata;
- s->name = pa_xstrdup(name);
- s->state = STREAM_CREATING;
- s->direction = dir;
- s->sample_spec = *ss;
- if (attr)
- s->buffer_attr = *attr;
- else {
- s->buffer_attr.maxlength = DEFAULT_MAXLENGTH;
- s->buffer_attr.tlength = DEFAULT_TLENGTH;
- s->buffer_attr.prebuf = DEFAULT_PREBUF;
- s->buffer_attr.minreq = DEFAULT_MINREQ;
- s->buffer_attr.fragsize = DEFAULT_FRAGSIZE;
- }
-
- create_stream(s, dev);
-
- return s;
-}
-
-void pa_stream_free(struct pa_stream *s) {
- assert(s && s->context);
-
- if (s->context->pdispatch)
- pa_pdispatch_unregister_reply(s->context->pdispatch, s);
-
- pa_xfree(s->name);
-
- if (s->channel_valid && s->context->state == CONTEXT_READY) {
- struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM :
- (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM));
- pa_tagstruct_putu32(t, s->context->ctag++);
- pa_tagstruct_putu32(t, s->channel);
- pa_pstream_send_tagstruct(s->context->pstream, t);
- }
-
- if (s->channel_valid)
- pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL);
-
- if (s->next)
- s->next->previous = s->previous;
- if (s->previous)
- s->previous->next = s->next;
- else
- s->context->first_stream = s->next;
-
- pa_xfree(s);
-}
-
-void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) {
- s->write_callback = cb;
- s->write_userdata = userdata;
-}
-
-void pa_stream_write(struct pa_stream *s, const void *data, size_t length) {
- struct pa_memchunk chunk;
- assert(s && s->context && data && length && s->state == STREAM_READY);
-
- chunk.memblock = pa_memblock_new(length);
- assert(chunk.memblock && chunk.memblock->data);
- memcpy(chunk.memblock->data, data, length);
- chunk.index = 0;
- chunk.length = length;
-
- pa_pstream_send_memblock(s->context->pstream, s->channel, 0, &chunk);
- pa_memblock_unref(chunk.memblock);
-
- /*fprintf(stderr, "Sent %u bytes\n", length);*/
-
- if (length < s->requested_bytes)
- s->requested_bytes -= length;
- else
- s->requested_bytes = 0;
-}
+void pa_create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
+void pa_stream_disconnect_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
+void pa_context_simple_ack_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
+void pa_stream_simple_ack_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-size_t pa_stream_writable_size(struct pa_stream *s) {
- assert(s && s->state == STREAM_READY);
- return s->requested_bytes;
-}
+void pa_context_fail(struct pa_context *c, int error);
+void pa_context_set_state(struct pa_context *c, enum pa_context_state st);
+int pa_context_handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t);
+struct pa_operation* pa_context_send_simple_command(struct pa_context *c, uint32_t command, void (*internal_callback)(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata), void (*cb)(), void *userdata);
-void pa_stream_set_read_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) {
- assert(s && cb);
- s->read_callback = cb;
- s->read_userdata = userdata;
-}
+void pa_stream_set_state(struct pa_stream *s, enum pa_stream_state st);
-int pa_stream_is_dead(struct pa_stream *s) {
- return s->state == STREAM_DEAD;
-}
-
-int pa_stream_is_ready(struct pa_stream*s) {
- return s->state == STREAM_READY;
-}
-
-void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata) {
- assert(s);
- s->die_callback = cb;
- s->die_userdata = userdata;
-}
-
-int pa_context_is_pending(struct pa_context *c) {
- assert(c);
-
- if (c->state != CONTEXT_READY)
- return 0;
-
- return pa_pstream_is_pending(c->pstream) || pa_pdispatch_is_pending(c->pdispatch);
-}
-
-struct pa_context* pa_stream_get_context(struct pa_stream *p) {
- assert(p);
- return p->context;
-}
-
-static void set_dispatch_callbacks(struct pa_context *c);
-
-static void pdispatch_drain_callback(struct pa_pdispatch*pd, void *userdata) {
- set_dispatch_callbacks(userdata);
-}
-
-static void pstream_drain_callback(struct pa_pstream *s, void *userdata) {
- set_dispatch_callbacks(userdata);
-}
-
-static void set_dispatch_callbacks(struct pa_context *c) {
- assert(c && c->state == CONTEXT_READY);
-
- pa_pstream_set_drain_callback(c->pstream, NULL, NULL);
- pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL);
-
- if (pa_pdispatch_is_pending(c->pdispatch)) {
- pa_pdispatch_set_drain_callback(c->pdispatch, pdispatch_drain_callback, c);
- return;
- }
-
- if (pa_pstream_is_pending(c->pstream)) {
- pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c);
- return;
- }
-
- assert(c->drain_complete_callback);
- c->drain_complete_callback(c, c->drain_complete_userdata);
-}
-
-int pa_context_drain(
- struct pa_context *c,
- void (*complete) (struct pa_context*c, void *userdata),
- void *userdata) {
-
- assert(c && c->state == CONTEXT_READY);
-
- if (complete == NULL) {
- c->drain_complete_callback = NULL;
- pa_pstream_set_drain_callback(c->pstream, NULL, NULL);
- pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL);
- return 0;
- }
-
- if (!pa_context_is_pending(c))
- return -1;
-
- c->drain_complete_callback = complete;
- c->drain_complete_userdata = userdata;
-
- set_dispatch_callbacks(c);
-
- return 0;
-}
-
-static void stream_drain_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- stream_dead(s);
- return;
- }
-
- if (s->state != STREAM_READY)
- return;
-
- if (!pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->drain_complete_callback) {
- void (*temp) (struct pa_stream*s, void *userdata) = s->drain_complete_callback;
- s->drain_complete_callback = NULL;
- temp(s, s->drain_complete_userdata);
- }
-}
-
-
-void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(s && s->state == STREAM_READY);
-
- if (!complete) {
- s->drain_complete_callback = NULL;
- return;
- }
-
- s->drain_complete_callback = complete;
- s->drain_complete_userdata = userdata;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, PA_COMMAND_DRAIN_PLAYBACK_STREAM);
- pa_tagstruct_putu32(t, tag = s->context->ctag++);
- pa_tagstruct_putu32(t, s->channel);
- pa_pstream_send_tagstruct(s->context->pstream, t);
- pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_drain_callback, s);
-}
-
-void pa_context_exit(struct pa_context *c) {
- struct pa_tagstruct *t;
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_EXIT);
- pa_tagstruct_putu32(t, c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
-}
-
-static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- uint32_t total, count;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->stat_callback)
- c->stat_callback(c, (uint32_t) -1, (uint32_t) -1, c->stat_userdata);
- return;
- }
-
- if (pa_tagstruct_getu32(t, &count) < 0 ||
- pa_tagstruct_getu32(t, &total) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->stat_callback)
- c->stat_callback(c, count, total, c->stat_userdata);
-}
-
-void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata) {
- uint32_t tag;
- struct pa_tagstruct *t;
-
- c->stat_callback = cb;
- c->stat_userdata = userdata;
-
- if (cb == NULL)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_STAT);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_stat_callback, c);
-}
-
-static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- uint32_t latency;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- if (s->get_latency_callback)
- s->get_latency_callback(s, (uint32_t) -1, s->get_latency_userdata);
- return;
- }
-
- if (pa_tagstruct_getu32(t, &latency) < 0 ||
- !pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->get_latency_callback)
- s->get_latency_callback(s, latency, s->get_latency_userdata);
-}
-
-void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata) {
- uint32_t tag;
- struct pa_tagstruct *t;
-
- p->get_latency_callback = cb;
- p->get_latency_userdata = userdata;
-
- if (cb == NULL)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY);
- pa_tagstruct_putu32(t, tag = p->context->ctag++);
- pa_tagstruct_putu32(t, p->channel);
- pa_pstream_send_tagstruct(p->context->pstream, t);
- pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, p);
-}
-
-struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) {
- struct pa_stream *s;
- struct pa_tagstruct *t;
- uint32_t tag;
-
- s = internal_stream_new(c);
- assert(s);
-
- s->create_complete_callback = cb;
- s->create_complete_userdata = userdata;
- s->name = pa_xstrdup(name);
- s->state = STREAM_CREATING;
- s->direction = PA_STREAM_UPLOAD;
- s->sample_spec = *ss;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_CREATE_UPLOAD_STREAM);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, name);
- pa_tagstruct_put_sample_spec(t, ss);
- pa_tagstruct_putu32(t, length);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s);
-
- return s;
-}
-
-static void stream_finish_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- if (s->finish_sample_callback)
- s->finish_sample_callback(s, 0, s->finish_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->finish_sample_callback)
- s->finish_sample_callback(s, 1, s->finish_sample_userdata);
-}
-
-void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(p);
-
- p->finish_sample_callback = cb;
- p->finish_sample_userdata = userdata;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_FINISH_UPLOAD_STREAM);
- pa_tagstruct_putu32(t, tag = p->context->ctag++);
- pa_tagstruct_putu32(t, p->channel);
- pa_pstream_send_tagstruct(p->context->pstream, t);
- pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_finish_sample_callback, p);
-}
-
-static void context_play_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->play_sample_callback)
- c->play_sample_callback(c, 0, c->play_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->play_sample_callback)
- c->play_sample_callback(c, 1, c->play_sample_userdata);
-}
-
-void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c && name && *name && (!dev || *dev));
-
- c->play_sample_callback = cb;
- c->play_sample_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_PLAY_SAMPLE);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, (uint32_t) -1);
- pa_tagstruct_puts(t, dev ? dev : "");
- pa_tagstruct_putu32(t, volume);
- pa_tagstruct_puts(t, name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_play_sample_callback, c);
-}
-
-static void context_remove_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->remove_sample_callback)
- c->remove_sample_callback(c, 0, c->remove_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->remove_sample_callback)
- c->remove_sample_callback(c, 1, c->remove_sample_userdata);
-}
-
-void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c && name);
-
- c->remove_sample_callback = cb;
- c->remove_sample_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_SAMPLE);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_remove_sample_callback, c);
-}
-
-static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_server_info i;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_server_info_callback)
- c->get_server_info_callback(c, NULL, c->get_server_info_userdata);
- return;
- }
-
- if (pa_tagstruct_gets(t, &i.server_name) < 0 ||
- pa_tagstruct_gets(t, &i.server_version) < 0 ||
- pa_tagstruct_gets(t, &i.user_name) < 0 ||
- pa_tagstruct_gets(t, &i.host_name) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_server_info_callback)
- c->get_server_info_callback(c, &i, c->get_server_info_userdata);
-}
-
-void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_server_info_callback = cb;
- c->get_server_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SERVER_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_server_info_callback, c);
-}
-
-static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, NULL, 0, c->get_sink_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_sink_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.description) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
- pa_tagstruct_getu32(t, &i.volume) < 0 ||
- pa_tagstruct_getu32(t, &i.monitor_source) < 0 ||
- pa_tagstruct_gets(t, &i.monitor_source_name) < 0 ||
- pa_tagstruct_getu32(t, &i.latency) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, &i, 0, c->get_sink_info_userdata);
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, NULL, 1, c->get_sink_info_userdata);
-}
-
-void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_sink_info_callback = cb;
- c->get_sink_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c);
-}
-
-static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, NULL, 0, c->get_source_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_source_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.description) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
- pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 ||
- pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, &i, 0, c->get_source_info_userdata);
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, NULL, 1, c->get_source_info_userdata);
-}
-
-void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_source_info_callback = cb;
- c->get_source_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c);
-}
-
-void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- assert(c);
-
- c->subscribe_callback = cb;
- c->subscribe_userdata = userdata;
- c->subscribe_mask = m;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE);
- pa_tagstruct_putu32(t, c->ctag++);
- pa_tagstruct_putu32(t, cb ? m : 0);
- pa_pstream_send_tagstruct(c->pstream, t);
-}
-
-static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- enum pa_subscription_event_type e;
- uint32_t index;
- assert(pd && command == PA_COMMAND_SUBSCRIBE_EVENT && t && c);
-
- if (pa_tagstruct_getu32(t, &e) < 0 ||
- pa_tagstruct_getu32(t, &index) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (pa_subscription_match_flags(c->subscribe_mask, e) && c->subscribe_callback)
- c->subscribe_callback(c, e, index, c->subscribe_userdata);
-}
-
-void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_sink_info_callback = cb;
- c->get_sink_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_tagstruct_puts(t, "");
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c);
-}
-
-void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_source_info_callback = cb;
- c->get_source_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_tagstruct_puts(t, "");
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c);
-}
-
-static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, NULL, 0, c->get_client_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_client_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.protocol_name) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, &i, 0, c->get_client_info_userdata);
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, NULL, 1, c->get_client_info_userdata);
-}
-
-
-void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_client_info_callback = cb;
- c->get_client_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c);
-}
-
-void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_client_info_callback = cb;
- c->get_client_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c);
-}
-
-static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, NULL, 0, c->get_module_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_module_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.argument) < 0 ||
- pa_tagstruct_getu32(t, &i.n_used) < 0 ||
- pa_tagstruct_getu32(t, &i.auto_unload) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, &i, 0, c->get_module_info_userdata);
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, NULL, 1, c->get_module_info_userdata);
-}
-
-void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_module_info_callback = cb;
- c->get_module_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c);
-}
-
-void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_module_info_callback = cb;
- c->get_module_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c);
-}
+#endif
diff --git a/polyp/polyplib-introspect.c b/polyp/polyplib-introspect.c
index 35001d3d..345a9cd5 100644
--- a/polyp/polyplib-introspect.c
+++ b/polyp/polyplib-introspect.c
@@ -23,1528 +23,421 @@
#include <config.h>
#endif
-#include <stdio.h>
#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-
-#include "polyplib.h"
-#include "native-common.h"
-#include "pdispatch.h"
-#include "pstream.h"
-#include "dynarray.h"
-#include "socket-client.h"
-#include "pstream-util.h"
-#include "authkey.h"
-#include "util.h"
-#include "xmalloc.h"
-
-#define DEFAULT_MAXLENGTH 204800
-#define DEFAULT_TLENGTH 10240
-#define DEFAULT_PREBUF 4096
-#define DEFAULT_MINREQ 1024
-#define DEFAULT_FRAGSIZE 1024
-
-#define DEFAULT_TIMEOUT (5*60)
-#define DEFAULT_SERVER "/tmp/polypaudio/native"
-#define DEFAULT_PORT "4713"
-
-struct pa_context {
- char *name;
- struct pa_mainloop_api* mainloop;
- struct pa_socket_client *client;
- struct pa_pstream *pstream;
- struct pa_pdispatch *pdispatch;
- struct pa_dynarray *record_streams, *playback_streams;
- struct pa_stream *first_stream;
- uint32_t ctag;
- uint32_t error;
- enum {
- CONTEXT_UNCONNECTED,
- CONTEXT_CONNECTING,
- CONTEXT_AUTHORIZING,
- CONTEXT_SETTING_NAME,
- CONTEXT_READY,
- CONTEXT_DEAD
- } state;
-
- void (*connect_complete_callback)(struct pa_context*c, int success, void *userdata);
- void *connect_complete_userdata;
-
- void (*drain_complete_callback)(struct pa_context*c, void *userdata);
- void *drain_complete_userdata;
-
- void (*die_callback)(struct pa_context*c, void *userdata);
- void *die_userdata;
-
- void (*stat_callback)(struct pa_context*c, uint32_t count, uint32_t total, void *userdata);
- void *stat_userdata;
-
- void (*play_sample_callback)(struct pa_context*c, int success, void *userdata);
- void *play_sample_userdata;
-
- void (*remove_sample_callback)(struct pa_context*c, int success, void *userdata);
- void *remove_sample_userdata;
-
- void (*get_server_info_callback)(struct pa_context*c, const struct pa_server_info* i, void *userdata);
- void *get_server_info_userdata;
-
- void (*get_sink_info_callback)(struct pa_context*c, const struct pa_sink_info* i, int is_last, void *userdata);
- void *get_sink_info_userdata;
-
- void (*get_source_info_callback)(struct pa_context*c, const struct pa_source_info* i, int is_last, void *userdata);
- void *get_source_info_userdata;
-
- void (*subscribe_callback)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata);
- void *subscribe_userdata;
- enum pa_subscription_mask subscribe_mask;
-
- void (*get_client_info_callback)(struct pa_context*c, const struct pa_client_info* i, int is_last, void *userdata);
- void *get_client_info_userdata;
-
- void (*get_module_info_callback)(struct pa_context*c, const struct pa_module_info* i, int is_last, void *userdata);
- void *get_module_info_userdata;
-
- uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH];
-};
-
-struct pa_stream {
- struct pa_context *context;
- struct pa_stream *next, *previous;
-
- char *name;
- struct pa_buffer_attr buffer_attr;
- struct pa_sample_spec sample_spec;
- uint32_t channel;
- int channel_valid;
- uint32_t device_index;
- enum pa_stream_direction direction;
-
- enum { STREAM_CREATING, STREAM_READY, STREAM_DEAD} state;
- uint32_t requested_bytes;
-
- void (*read_callback)(struct pa_stream *p, const void*data, size_t length, void *userdata);
- void *read_userdata;
-
- void (*write_callback)(struct pa_stream *p, size_t length, void *userdata);
- void *write_userdata;
-
- void (*create_complete_callback)(struct pa_stream *s, int success, void *userdata);
- void *create_complete_userdata;
-
- void (*drain_complete_callback)(struct pa_stream *s, void *userdata);
- void *drain_complete_userdata;
-
- void (*die_callback)(struct pa_stream*c, void *userdata);
- void *die_userdata;
-
- void (*get_latency_callback)(struct pa_stream*c, uint32_t latency, void *userdata);
- void *get_latency_userdata;
-
- void (*finish_sample_callback)(struct pa_stream*c, int success, void *userdata);
- void *finish_sample_userdata;
-};
-
-static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-
-static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = {
- [PA_COMMAND_ERROR] = { NULL },
- [PA_COMMAND_REPLY] = { NULL },
- [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { NULL },
- [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { NULL },
- [PA_COMMAND_CREATE_RECORD_STREAM] = { NULL },
- [PA_COMMAND_DELETE_RECORD_STREAM] = { NULL },
- [PA_COMMAND_EXIT] = { NULL },
- [PA_COMMAND_REQUEST] = { command_request },
- [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { command_playback_stream_killed },
- [PA_COMMAND_RECORD_STREAM_KILLED] = { command_playback_stream_killed },
- [PA_COMMAND_SUBSCRIBE_EVENT] = { command_subscribe_event },
-};
-
-struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) {
- struct pa_context *c;
- assert(mainloop && name);
-
- c = pa_xmalloc(sizeof(struct pa_context));
- c->name = pa_xstrdup(name);
- c->mainloop = mainloop;
- c->client = NULL;
- c->pstream = NULL;
- c->pdispatch = NULL;
- c->playback_streams = pa_dynarray_new();
- assert(c->playback_streams);
- c->record_streams = pa_dynarray_new();
- assert(c->record_streams);
- c->first_stream = NULL;
- c->error = PA_ERROR_OK;
- c->state = CONTEXT_UNCONNECTED;
- c->ctag = 0;
-
- c->connect_complete_callback = NULL;
- c->connect_complete_userdata = NULL;
-
- c->drain_complete_callback = NULL;
- c->drain_complete_userdata = NULL;
-
- c->die_callback = NULL;
- c->die_userdata = NULL;
-
- c->stat_callback = NULL;
- c->stat_userdata = NULL;
-
- c->play_sample_callback = NULL;
- c->play_sample_userdata = NULL;
-
- c->remove_sample_callback = NULL;
- c->remove_sample_userdata = NULL;
-
- c->get_server_info_callback = NULL;
- c->get_server_info_userdata = NULL;
- c->get_sink_info_callback = NULL;
- c->get_sink_info_userdata = NULL;
-
- c->get_source_info_callback = NULL;
- c->get_source_info_userdata = NULL;
-
- c->subscribe_callback = NULL;
- c->subscribe_userdata = NULL;
-
- c->get_client_info_callback = NULL;
- c->get_client_info_userdata = NULL;
-
- c->get_module_info_callback = NULL;
- c->get_module_info_userdata = NULL;
-
- pa_check_for_sigpipe();
- return c;
-}
-
-void pa_context_free(struct pa_context *c) {
- assert(c);
-
- while (c->first_stream)
- pa_stream_free(c->first_stream);
-
- if (c->client)
- pa_socket_client_free(c->client);
- if (c->pdispatch)
- pa_pdispatch_free(c->pdispatch);
- if (c->pstream)
- pa_pstream_free(c->pstream);
- if (c->record_streams)
- pa_dynarray_free(c->record_streams, NULL, NULL);
- if (c->playback_streams)
- pa_dynarray_free(c->playback_streams, NULL, NULL);
-
- pa_xfree(c->name);
- pa_xfree(c);
-}
-
-static void stream_dead(struct pa_stream *s) {
- assert(s);
-
- if (s->state == STREAM_DEAD)
- return;
-
- if (s->state == STREAM_READY) {
- s->state = STREAM_DEAD;
- if (s->die_callback)
- s->die_callback(s, s->die_userdata);
- } else
- s->state = STREAM_DEAD;
-}
-
-static void context_dead(struct pa_context *c) {
- struct pa_stream *s;
- assert(c);
-
- if (c->state == CONTEXT_DEAD)
- return;
-
- if (c->pdispatch)
- pa_pdispatch_free(c->pdispatch);
- c->pdispatch = NULL;
-
- if (c->pstream)
- pa_pstream_free(c->pstream);
- c->pstream = NULL;
-
- if (c->client)
- pa_socket_client_free(c->client);
- c->client = NULL;
-
- for (s = c->first_stream; s; s = s->next)
- stream_dead(s);
-
- if (c->state == CONTEXT_READY) {
- c->state = CONTEXT_DEAD;
- if (c->die_callback)
- c->die_callback(c, c->die_userdata);
- } else
- c->state = CONTEXT_DEAD;
-}
-
-static void pstream_die_callback(struct pa_pstream *p, void *userdata) {
- struct pa_context *c = userdata;
- assert(p && c);
- c->error = PA_ERROR_CONNECTIONTERMINATED;
- context_dead(c);
-}
-
-static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) {
- struct pa_context *c = userdata;
- assert(p && packet && c);
-
- if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) {
- fprintf(stderr, "polyp.c: invalid packet.\n");
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- }
-}
-
-static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_stream *s;
- assert(p && chunk && c && chunk->memblock && chunk->memblock->data);
-
- if (!(s = pa_dynarray_get(c->record_streams, channel)))
- return;
-
- if (s->read_callback)
- s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata);
-}
-
-static int handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t) {
- assert(c && t);
-
- if (command == PA_COMMAND_ERROR) {
- if (pa_tagstruct_getu32(t, &c->error) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- return -1;
- }
+#include "polyplib-introspect.h"
+#include "polyplib-context.h"
+#include "polyplib-internal.h"
+#include "pstream-util.h"
- return 0;
- }
+/*** Statistics ***/
- c->error = (command == PA_COMMAND_TIMEOUT) ? PA_ERROR_TIMEOUT : PA_ERROR_INTERNAL;
- return -1;
-}
-
-static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c && (c->state == CONTEXT_AUTHORIZING || c->state == CONTEXT_SETTING_NAME));
+static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
+ struct pa_operation *o = userdata;
+ struct pa_stat_info i, *p = &i;
+ assert(pd && o && o->context && o->ref >= 1);
if (command != PA_COMMAND_REPLY) {
- handle_error(c, command, t);
- context_dead(c);
+ if (pa_context_handle_error(o->context, command, t) < 0)
+ goto finish;
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 0, c->connect_complete_userdata);
-
- return;
+ p = NULL;
+ } else if (pa_tagstruct_getu32(t, &i.memblock_count) < 0 ||
+ pa_tagstruct_getu32(t, &i.memblock_total) < 0 ||
+ !pa_tagstruct_eof(t)) {
+ pa_context_fail(o->context, PA_ERROR_PROTOCOL);
+ goto finish;
}
- if (c->state == CONTEXT_AUTHORIZING) {
- struct pa_tagstruct *t;
- c->state = CONTEXT_SETTING_NAME;
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_SET_NAME);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, c->name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c);
- } else {
- assert(c->state == CONTEXT_SETTING_NAME);
-
- c->state = CONTEXT_READY;
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 1, c->connect_complete_userdata);
+ if (o->callback) {
+ void (*cb)(struct pa_context *s, const struct pa_stat_info*i, void *userdata) = o->callback;
+ cb(o->context, p, o->userdata);
}
- return;
+finish:
+ pa_operation_done(o);
+ pa_operation_unref(o);
}
-static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(client && c && c->state == CONTEXT_CONNECTING);
-
- pa_socket_client_free(client);
- c->client = NULL;
-
- if (!io) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- context_dead(c);
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 0, c->connect_complete_userdata);
-
- return;
- }
-
- c->pstream = pa_pstream_new(c->mainloop, io);
- assert(c->pstream);
- pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c);
- pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c);
- pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c);
-
- c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX);
- assert(c->pdispatch);
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_AUTH);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_put_arbitrary(t, c->auth_cookie, sizeof(c->auth_cookie));
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c);
- c->state = CONTEXT_AUTHORIZING;
+struct pa_operation* pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_stat_info*i, void *userdata), void *userdata) {
+ return pa_context_send_simple_command(c, PA_COMMAND_STAT, context_stat_callback, cb, userdata);
}
-static struct sockaddr *resolve_server(const char *server, size_t *len) {
- struct sockaddr *sa;
- struct addrinfo hints, *result = NULL;
- char *port;
- assert(server && len);
-
- if ((port = strrchr(server, ':')))
- port++;
- if (!port)
- port = DEFAULT_PORT;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = 0;
-
- if (getaddrinfo(server, port, &hints, &result) != 0)
- return NULL;
- assert(result);
-
- sa = pa_xmalloc(*len = result->ai_addrlen);
- memcpy(sa, result->ai_addr, *len);
+/*** Server Info ***/
- freeaddrinfo(result);
-
- return sa;
-}
+static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
+ struct pa_operation *o = userdata;
+ struct pa_server_info i, *p = &i;
+ assert(pd && o && o->context && o->ref >= 1);
-int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata) {
- assert(c && c->state == CONTEXT_UNCONNECTED);
+ if (command != PA_COMMAND_REPLY) {
+ if (pa_context_handle_error(o->context, command, t) < 0)
+ goto finish;
- if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE, c->auth_cookie, sizeof(c->auth_cookie)) < 0) {
- c->error = PA_ERROR_AUTHKEY;
- return -1;
+ p = NULL;
+ } else if (pa_tagstruct_gets(t, &i.server_name) < 0 ||
+ pa_tagstruct_gets(t, &i.server_version) < 0 ||
+ pa_tagstruct_gets(t, &i.user_name) < 0 ||
+ pa_tagstruct_gets(t, &i.host_name) < 0 ||
+ pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
+ !pa_tagstruct_eof(t)) {
+ pa_context_fail(o->context, PA_ERROR_PROTOCOL);
+ goto finish;
}
-
- if (!server)
- if (!(server = getenv("POLYP_SERVER")))
- server = DEFAULT_SERVER;
-
- assert(!c->client);
- if (*server == '/') {
- if (!(c->client = pa_socket_client_new_unix(c->mainloop, server))) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- return -1;
- }
- } else {
- struct sockaddr* sa;
- size_t sa_len;
-
- if (!(sa = resolve_server(server, &sa_len))) {
- c->error = PA_ERROR_INVALIDSERVER;
- return -1;
- }
-
- c->client = pa_socket_client_new_sockaddr(c->mainloop, sa, sa_len);
- pa_xfree(sa);
-
- if (!c->client) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- return -1;
- }
+ if (o->callback) {
+ void (*cb)(struct pa_context *s, const struct pa_server_info*i, void *userdata) = o->callback;
+ cb(o->context, p, o->userdata);
}
- c->connect_complete_callback = complete;
- c->connect_complete_userdata = userdata;
-
- pa_socket_client_set_callback(c->client, on_connection, c);
- c->state = CONTEXT_CONNECTING;
-
- return 0;
-}
-
-int pa_context_is_dead(struct pa_context *c) {
- assert(c);
- return c->state == CONTEXT_DEAD;
+finish:
+ pa_operation_done(o);
+ pa_operation_unref(o);
}
-int pa_context_is_ready(struct pa_context *c) {
- assert(c);
- return c->state == CONTEXT_READY;
+struct pa_operation* pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata) {
+ return pa_context_send_simple_command(c, PA_COMMAND_GET_SERVER_INFO, context_get_server_info_callback, cb, userdata);
}
-int pa_context_errno(struct pa_context *c) {
- assert(c);
- return c->error;
-}
-
-void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata) {
- assert(c);
- c->die_callback = cb;
- c->die_userdata = userdata;
-}
-
-static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_stream *s;
- uint32_t channel;
- assert(pd && (command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED) && t && c);
-
- if (pa_tagstruct_getu32(t, &channel) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel)))
- return;
+/*** Sink Info ***/
- c->error = PA_ERROR_KILLED;
- stream_dead(s);
-}
-
-static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s;
- struct pa_context *c = userdata;
- uint32_t bytes, channel;
- assert(pd && command == PA_COMMAND_REQUEST && t && c);
-
- if (pa_tagstruct_getu32(t, &channel) < 0 ||
- pa_tagstruct_getu32(t, &bytes) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (!(s = pa_dynarray_get(c->playback_streams, channel)))
- return;
-
- if (s->state != STREAM_READY)
- return;
-
- s->requested_bytes += bytes;
-
- if (s->requested_bytes && s->write_callback)
- s->write_callback(s, s->requested_bytes, s->write_userdata);
-}
-
-static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s && s->state == STREAM_CREATING);
+static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
+ struct pa_operation *o = userdata;
+ int eof = 1;
+ assert(pd && o && o->context && o->ref >= 1);
if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- stream_dead(s);
- if (s->create_complete_callback)
- s->create_complete_callback(s, 0, s->create_complete_userdata);
-
- return;
- }
-
- if (pa_tagstruct_getu32(t, &s->channel) < 0 ||
- ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) ||
- !pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- s->channel_valid = 1;
- pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s);
-
- s->state = STREAM_READY;
- if (s->create_complete_callback)
- s->create_complete_callback(s, 1, s->create_complete_userdata);
-}
-
-static void create_stream(struct pa_stream *s, const char *dev) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(s);
-
- s->state = STREAM_CREATING;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM);
- pa_tagstruct_putu32(t, tag = s->context->ctag++);
- pa_tagstruct_puts(t, s->name);
- pa_tagstruct_put_sample_spec(t, &s->sample_spec);
- pa_tagstruct_putu32(t, (uint32_t) -1);
- pa_tagstruct_puts(t, dev ? dev : "");
- pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
- if (s->direction == PA_STREAM_PLAYBACK) {
- pa_tagstruct_putu32(t, s->buffer_attr.tlength);
- pa_tagstruct_putu32(t, s->buffer_attr.prebuf);
- pa_tagstruct_putu32(t, s->buffer_attr.minreq);
- } else
- pa_tagstruct_putu32(t, s->buffer_attr.fragsize);
-
- pa_pstream_send_tagstruct(s->context->pstream, t);
- pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s);
-}
+ if (pa_context_handle_error(o->context, command, t) < 0)
+ goto finish;
-static struct pa_stream *internal_stream_new(struct pa_context *c) {
- struct pa_stream *s;
-
- s = pa_xmalloc(sizeof(struct pa_stream));
- s->context = c;
-
- s->read_callback = NULL;
- s->read_userdata = NULL;
- s->write_callback = NULL;
- s->write_userdata = NULL;
- s->die_callback = NULL;
- s->die_userdata = NULL;
- s->create_complete_callback = NULL;
- s->create_complete_userdata = NULL;
- s->get_latency_callback = NULL;
- s->get_latency_userdata = NULL;
- s->finish_sample_callback = NULL;
- s->finish_sample_userdata = NULL;
-
- s->name = NULL;
- s->state = STREAM_CREATING;
- s->requested_bytes = 0;
- s->channel = 0;
- s->channel_valid = 0;
- s->device_index = (uint32_t) -1;
-
- memset(&s->buffer_attr, 0, sizeof(s->buffer_attr));
-
- s->next = c->first_stream;
- if (s->next)
- s->next->previous = s;
- s->previous = NULL;
- c->first_stream = s;
-
- return s;
-}
-
-struct pa_stream* pa_stream_new(
- struct pa_context *c,
- enum pa_stream_direction dir,
- const char *dev,
- const char *name,
- const struct pa_sample_spec *ss,
- const struct pa_buffer_attr *attr,
- void (*complete) (struct pa_stream*s, int success, void *userdata),
- void *userdata) {
-
- struct pa_stream *s;
-
- assert(c && name && ss && c->state == CONTEXT_READY && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD));
-
- s = internal_stream_new(c);
- assert(s);
-
- s->create_complete_callback = complete;
- s->create_complete_userdata = userdata;
- s->name = pa_xstrdup(name);
- s->state = STREAM_CREATING;
- s->direction = dir;
- s->sample_spec = *ss;
- if (attr)
- s->buffer_attr = *attr;
- else {
- s->buffer_attr.maxlength = DEFAULT_MAXLENGTH;
- s->buffer_attr.tlength = DEFAULT_TLENGTH;
- s->buffer_attr.prebuf = DEFAULT_PREBUF;
- s->buffer_attr.minreq = DEFAULT_MINREQ;
- s->buffer_attr.fragsize = DEFAULT_FRAGSIZE;
- }
-
- create_stream(s, dev);
-
- return s;
-}
-
-void pa_stream_free(struct pa_stream *s) {
- assert(s && s->context);
-
- if (s->context->pdispatch)
- pa_pdispatch_unregister_reply(s->context->pdispatch, s);
-
- pa_xfree(s->name);
-
- if (s->channel_valid && s->context->state == CONTEXT_READY) {
- struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM :
- (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM));
- pa_tagstruct_putu32(t, s->context->ctag++);
- pa_tagstruct_putu32(t, s->channel);
- pa_pstream_send_tagstruct(s->context->pstream, t);
+ eof = -1;
+ } else {
+
+ while (!pa_tagstruct_eof(t)) {
+ struct pa_sink_info i;
+
+ if (pa_tagstruct_getu32(t, &i.index) < 0 ||
+ pa_tagstruct_gets(t, &i.name) < 0 ||
+ pa_tagstruct_gets(t, &i.description) < 0 ||
+ pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
+ pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
+ pa_tagstruct_getu32(t, &i.volume) < 0 ||
+ pa_tagstruct_getu32(t, &i.monitor_source) < 0 ||
+ pa_tagstruct_gets(t, &i.monitor_source_name) < 0 ||
+ pa_tagstruct_getu32(t, &i.latency) < 0) {
+ pa_context_fail(o->context, PA_ERROR_PROTOCOL);
+ goto finish;
+ }
+
+ if (o->callback) {
+ void (*cb)(struct pa_context *s, const struct pa_sink_info*i, int eof, void *userdata) = o->callback;
+ cb(o->context, &i, 0, o->userdata);
+ }
+ }
}
- if (s->channel_valid)
- pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL);
-
- if (s->next)
- s->next->previous = s->previous;
- if (s->previous)
- s->previous->next = s->next;
- else
- s->context->first_stream = s->next;
-
- pa_xfree(s);
-}
-
-void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) {
- s->write_callback = cb;
- s->write_userdata = userdata;
-}
-
-void pa_stream_write(struct pa_stream *s, const void *data, size_t length) {
- struct pa_memchunk chunk;
- assert(s && s->context && data && length && s->state == STREAM_READY);
-
- chunk.memblock = pa_memblock_new(length);
- assert(chunk.memblock && chunk.memblock->data);
- memcpy(chunk.memblock->data, data, length);
- chunk.index = 0;
- chunk.length = length;
-
- pa_pstream_send_memblock(s->context->pstream, s->channel, 0, &chunk);
- pa_memblock_unref(chunk.memblock);
-
- /*fprintf(stderr, "Sent %u bytes\n", length);*/
-
- if (length < s->requested_bytes)
- s->requested_bytes -= length;
- else
- s->requested_bytes = 0;
-}
-
-size_t pa_stream_writable_size(struct pa_stream *s) {
- assert(s && s->state == STREAM_READY);
- return s->requested_bytes;
-}
-
-void pa_stream_set_read_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) {
- assert(s && cb);
- s->read_callback = cb;
- s->read_userdata = userdata;
-}
-
-int pa_stream_is_dead(struct pa_stream *s) {
- return s->state == STREAM_DEAD;
-}
-
-int pa_stream_is_ready(struct pa_stream*s) {
- return s->state == STREAM_READY;
-}
-
-void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata) {
- assert(s);
- s->die_callback = cb;
- s->die_userdata = userdata;
-}
-
-int pa_context_is_pending(struct pa_context *c) {
- assert(c);
-
- if (c->state != CONTEXT_READY)
- return 0;
-
- return pa_pstream_is_pending(c->pstream) || pa_pdispatch_is_pending(c->pdispatch);
-}
-
-struct pa_context* pa_stream_get_context(struct pa_stream *p) {
- assert(p);
- return p->context;
-}
-
-static void set_dispatch_callbacks(struct pa_context *c);
-
-static void pdispatch_drain_callback(struct pa_pdispatch*pd, void *userdata) {
- set_dispatch_callbacks(userdata);
-}
-
-static void pstream_drain_callback(struct pa_pstream *s, void *userdata) {
- set_dispatch_callbacks(userdata);
-}
-
-static void set_dispatch_callbacks(struct pa_context *c) {
- assert(c && c->state == CONTEXT_READY);
-
- pa_pstream_set_drain_callback(c->pstream, NULL, NULL);
- pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL);
-
- if (pa_pdispatch_is_pending(c->pdispatch)) {
- pa_pdispatch_set_drain_callback(c->pdispatch, pdispatch_drain_callback, c);
- return;
- }
-
- if (pa_pstream_is_pending(c->pstream)) {
- pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c);
- return;
- }
-
- assert(c->drain_complete_callback);
- c->drain_complete_callback(c, c->drain_complete_userdata);
-}
-
-int pa_context_drain(
- struct pa_context *c,
- void (*complete) (struct pa_context*c, void *userdata),
- void *userdata) {
-
- assert(c && c->state == CONTEXT_READY);
-
- if (complete == NULL) {
- c->drain_complete_callback = NULL;
- pa_pstream_set_drain_callback(c->pstream, NULL, NULL);
- pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL);
- return 0;
+ if (o->callback) {
+ void (*cb)(struct pa_context *s, const struct pa_sink_info*i, int eof, void *userdata) = o->callback;
+ cb(o->context, NULL, eof, o->userdata);
}
-
- if (!pa_context_is_pending(c))
- return -1;
-
- c->drain_complete_callback = complete;
- c->drain_complete_userdata = userdata;
- set_dispatch_callbacks(c);
-
- return 0;
+finish:
+ pa_operation_done(o);
+ pa_operation_unref(o);
}
-static void stream_drain_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- stream_dead(s);
- return;
- }
-
- if (s->state != STREAM_READY)
- return;
-
- if (!pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->drain_complete_callback) {
- void (*temp) (struct pa_stream*s, void *userdata) = s->drain_complete_callback;
- s->drain_complete_callback = NULL;
- temp(s, s->drain_complete_userdata);
- }
+struct pa_operation* pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
+ return pa_context_send_simple_command(c, PA_COMMAND_GET_SINK_INFO_LIST, context_get_sink_info_callback, cb, userdata);
}
-
-void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata) {
+struct pa_operation* pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
struct pa_tagstruct *t;
+ struct pa_operation *o;
uint32_t tag;
- assert(s && s->state == STREAM_READY);
-
- if (!complete) {
- s->drain_complete_callback = NULL;
- return;
- }
+ assert(c && cb);
- s->drain_complete_callback = complete;
- s->drain_complete_userdata = userdata;
+ o = pa_operation_new(c, NULL);
+ o->callback = cb;
+ o->userdata = userdata;
t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, PA_COMMAND_DRAIN_PLAYBACK_STREAM);
- pa_tagstruct_putu32(t, tag = s->context->ctag++);
- pa_tagstruct_putu32(t, s->channel);
- pa_pstream_send_tagstruct(s->context->pstream, t);
- pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_drain_callback, s);
-}
-
-void pa_context_exit(struct pa_context *c) {
- struct pa_tagstruct *t;
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_EXIT);
- pa_tagstruct_putu32(t, c->ctag++);
+ pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO);
+ pa_tagstruct_putu32(t, tag = c->ctag++);
+ pa_tagstruct_putu32(t, index);
+ pa_tagstruct_puts(t, "");
pa_pstream_send_tagstruct(c->pstream, t);
-}
-
-static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- uint32_t total, count;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->stat_callback)
- c->stat_callback(c, (uint32_t) -1, (uint32_t) -1, c->stat_userdata);
- return;
- }
+ pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, o);
- if (pa_tagstruct_getu32(t, &count) < 0 ||
- pa_tagstruct_getu32(t, &total) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->stat_callback)
- c->stat_callback(c, count, total, c->stat_userdata);
+ return pa_operation_ref(o);
}
-void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata) {
- uint32_t tag;
- struct pa_tagstruct *t;
-
- c->stat_callback = cb;
- c->stat_userdata = userdata;
+/*** Source info ***/
- if (cb == NULL)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_STAT);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_stat_callback, c);
-}
-
-static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- uint32_t latency;
- assert(pd && s);
+static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
+ struct pa_operation *o = userdata;
+ int eof = 1;
+ assert(pd && o && o->context && o->ref >= 1);
if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
+ if (pa_context_handle_error(o->context, command, t) < 0)
+ goto finish;
- if (s->get_latency_callback)
- s->get_latency_callback(s, (uint32_t) -1, s->get_latency_userdata);
- return;
+ eof = -1;
+ } else {
+
+ while (!pa_tagstruct_eof(t)) {
+ struct pa_source_info i;
+
+ if (pa_tagstruct_getu32(t, &i.index) < 0 ||
+ pa_tagstruct_gets(t, &i.name) < 0 ||
+ pa_tagstruct_gets(t, &i.description) < 0 ||
+ pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
+ pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
+ pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 ||
+ pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0) {
+ pa_context_fail(o->context, PA_ERROR_PROTOCOL);
+ goto finish;
+ }
+
+ if (o->callback) {
+ void (*cb)(struct pa_context *s, const struct pa_source_info*i, int eof, void *userdata) = o->callback;
+ cb(o->context, &i, 0, o->userdata);
+ }
+ }
}
-
- if (pa_tagstruct_getu32(t, &latency) < 0 ||
- !pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
+
+ if (o->callback) {
+ void (*cb)(struct pa_context *s, const struct pa_source_info*i, int eof, void *userdata) = o->callback;
+ cb(o->context, NULL, eof, o->userdata);
}
- if (s->get_latency_callback)
- s->get_latency_callback(s, latency, s->get_latency_userdata);
+finish:
+ pa_operation_done(o);
+ pa_operation_unref(o);
}
-void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata) {
- uint32_t tag;
- struct pa_tagstruct *t;
-
- p->get_latency_callback = cb;
- p->get_latency_userdata = userdata;
-
- if (cb == NULL)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY);
- pa_tagstruct_putu32(t, tag = p->context->ctag++);
- pa_tagstruct_putu32(t, p->channel);
- pa_pstream_send_tagstruct(p->context->pstream, t);
- pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, p);
+struct pa_operation* pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
+ return pa_context_send_simple_command(c, PA_COMMAND_GET_SOURCE_INFO_LIST, context_get_source_info_callback, cb, userdata);
}
-struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) {
- struct pa_stream *s;
+struct pa_operation* pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
struct pa_tagstruct *t;
+ struct pa_operation *o;
uint32_t tag;
-
- s = internal_stream_new(c);
- assert(s);
+ assert(c && cb);
- s->create_complete_callback = cb;
- s->create_complete_userdata = userdata;
- s->name = pa_xstrdup(name);
- s->state = STREAM_CREATING;
- s->direction = PA_STREAM_UPLOAD;
- s->sample_spec = *ss;
+ o = pa_operation_new(c, NULL);
+ o->callback = cb;
+ o->userdata = userdata;
t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_CREATE_UPLOAD_STREAM);
+ pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO);
pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, name);
- pa_tagstruct_put_sample_spec(t, ss);
- pa_tagstruct_putu32(t, length);
+ pa_tagstruct_putu32(t, index);
+ pa_tagstruct_puts(t, "");
pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s);
+ pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, o);
- return s;
+ return pa_operation_ref(o);
}
-static void stream_finish_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- if (s->finish_sample_callback)
- s->finish_sample_callback(s, 0, s->finish_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->finish_sample_callback)
- s->finish_sample_callback(s, 1, s->finish_sample_userdata);
-}
-
-void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(p);
-
- p->finish_sample_callback = cb;
- p->finish_sample_userdata = userdata;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_FINISH_UPLOAD_STREAM);
- pa_tagstruct_putu32(t, tag = p->context->ctag++);
- pa_tagstruct_putu32(t, p->channel);
- pa_pstream_send_tagstruct(p->context->pstream, t);
- pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_finish_sample_callback, p);
-}
+/*** Client info ***/
-static void context_play_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
+static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
+ struct pa_operation *o = userdata;
+ int eof = 1;
+ assert(pd && o && o->context && o->ref >= 1);
if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
+ if (pa_context_handle_error(o->context, command, t) < 0)
+ goto finish;
- if (c->play_sample_callback)
- c->play_sample_callback(c, 0, c->play_sample_userdata);
- return;
+ eof = -1;
+ } else {
+
+ while (!pa_tagstruct_eof(t)) {
+ struct pa_client_info i;
+
+ if (pa_tagstruct_getu32(t, &i.index) < 0 ||
+ pa_tagstruct_gets(t, &i.name) < 0 ||
+ pa_tagstruct_gets(t, &i.protocol_name) < 0 ||
+ pa_tagstruct_getu32(t, &i.owner_module) < 0) {
+ pa_context_fail(o->context, PA_ERROR_PROTOCOL);
+ goto finish;
+ }
+
+ if (o->callback) {
+ void (*cb)(struct pa_context *s, const struct pa_client_info*i, int eof, void *userdata) = o->callback;
+ cb(o->context, &i, 0, o->userdata);
+ }
+ }
}
-
- if (!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
+
+ if (o->callback) {
+ void (*cb)(struct pa_context *s, const struct pa_client_info*i, int eof, void *userdata) = o->callback;
+ cb(o->context, NULL, eof, o->userdata);
}
- if (c->play_sample_callback)
- c->play_sample_callback(c, 1, c->play_sample_userdata);
+finish:
+ pa_operation_done(o);
+ pa_operation_unref(o);
}
-void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
+struct pa_operation* pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
struct pa_tagstruct *t;
+ struct pa_operation *o;
uint32_t tag;
- assert(c && name && *name && (!dev || *dev));
+ assert(c && cb);
- c->play_sample_callback = cb;
- c->play_sample_userdata = userdata;
-
- if (!cb)
- return;
+ o = pa_operation_new(c, NULL);
+ o->callback = cb;
+ o->userdata = userdata;
t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_PLAY_SAMPLE);
+ pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO);
pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, (uint32_t) -1);
- pa_tagstruct_puts(t, dev ? dev : "");
- pa_tagstruct_putu32(t, volume);
- pa_tagstruct_puts(t, name);
+ pa_tagstruct_putu32(t, index);
+ pa_tagstruct_puts(t, "");
pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_play_sample_callback, c);
-}
-
-static void context_remove_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->remove_sample_callback)
- c->remove_sample_callback(c, 0, c->remove_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->remove_sample_callback)
- c->remove_sample_callback(c, 1, c->remove_sample_userdata);
-}
-
-void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c && name);
+ pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, o);
- c->remove_sample_callback = cb;
- c->remove_sample_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_SAMPLE);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_remove_sample_callback, c);
+ return pa_operation_ref(o);
}
-static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_server_info i;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_server_info_callback)
- c->get_server_info_callback(c, NULL, c->get_server_info_userdata);
- return;
- }
-
- if (pa_tagstruct_gets(t, &i.server_name) < 0 ||
- pa_tagstruct_gets(t, &i.server_version) < 0 ||
- pa_tagstruct_gets(t, &i.user_name) < 0 ||
- pa_tagstruct_gets(t, &i.host_name) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_server_info_callback)
- c->get_server_info_callback(c, &i, c->get_server_info_userdata);
+struct pa_operation* pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
+ return pa_context_send_simple_command(c, PA_COMMAND_GET_CLIENT_INFO_LIST, context_get_client_info_callback, cb, userdata);
}
-void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_server_info_callback = cb;
- c->get_server_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SERVER_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_server_info_callback, c);
-}
+/*** Module info ***/
-static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
+static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
+ struct pa_operation *o = userdata;
+ int eof = 1;
+ assert(pd && o && o->context && o->ref >= 1);
if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
+ if (pa_context_handle_error(o->context, command, t) < 0)
+ goto finish;
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, NULL, 0, c->get_sink_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_sink_info i;
+ eof = -1;
+ } else {
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.description) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
- pa_tagstruct_getu32(t, &i.volume) < 0 ||
- pa_tagstruct_getu32(t, &i.monitor_source) < 0 ||
- pa_tagstruct_gets(t, &i.monitor_source_name) < 0 ||
- pa_tagstruct_getu32(t, &i.latency) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
+ while (!pa_tagstruct_eof(t)) {
+ struct pa_module_info i;
+
+ if (pa_tagstruct_getu32(t, &i.index) < 0 ||
+ pa_tagstruct_gets(t, &i.name) < 0 ||
+ pa_tagstruct_gets(t, &i.argument) < 0 ||
+ pa_tagstruct_getu32(t, &i.n_used) < 0 ||
+ pa_tagstruct_getu32(t, &i.auto_unload) < 0) {
+ pa_context_fail(o->context, PA_ERROR_PROTOCOL);
+ goto finish;
+ }
+
+ if (o->callback) {
+ void (*cb)(struct pa_context *s, const struct pa_module_info*i, int eof, void *userdata) = o->callback;
+ cb(o->context, &i, 0, o->userdata);
+ }
}
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, &i, 0, c->get_sink_info_userdata);
}
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, NULL, 1, c->get_sink_info_userdata);
-}
-
-void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_sink_info_callback = cb;
- c->get_sink_info_userdata = userdata;
-
- if (!cb)
- return;
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c);
-}
-
-static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, NULL, 0, c->get_source_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_source_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.description) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
- pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 ||
- pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, &i, 0, c->get_source_info_userdata);
+ if (o->callback) {
+ void (*cb)(struct pa_context *s, const struct pa_module_info*i, int eof, void *userdata) = o->callback;
+ cb(o->context, NULL, eof, o->userdata);
}
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, NULL, 1, c->get_source_info_userdata);
+finish:
+ pa_operation_done(o);
+ pa_operation_unref(o);
}
-void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
+struct pa_operation* pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
struct pa_tagstruct *t;
+ struct pa_operation *o;
uint32_t tag;
- assert(c);
+ assert(c && cb);
- c->get_source_info_callback = cb;
- c->get_source_info_userdata = userdata;
+ o = pa_operation_new(c, NULL);
+ o->callback = cb;
+ o->userdata = userdata;
- if (!cb)
- return;
-
t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO_LIST);
+ pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO);
pa_tagstruct_putu32(t, tag = c->ctag++);
+ pa_tagstruct_putu32(t, index);
pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c);
-}
-
-void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- assert(c);
+ pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, o);
- c->subscribe_callback = cb;
- c->subscribe_userdata = userdata;
- c->subscribe_mask = m;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE);
- pa_tagstruct_putu32(t, c->ctag++);
- pa_tagstruct_putu32(t, cb ? m : 0);
- pa_pstream_send_tagstruct(c->pstream, t);
+ return pa_operation_ref(o);
}
-static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- enum pa_subscription_event_type e;
- uint32_t index;
- assert(pd && command == PA_COMMAND_SUBSCRIBE_EVENT && t && c);
-
- if (pa_tagstruct_getu32(t, &e) < 0 ||
- pa_tagstruct_getu32(t, &index) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (pa_subscription_match_flags(c->subscribe_mask, e) && c->subscribe_callback)
- c->subscribe_callback(c, e, index, c->subscribe_userdata);
+struct pa_operation* pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
+ return pa_context_send_simple_command(c, PA_COMMAND_GET_MODULE_INFO_LIST, context_get_module_info_callback, cb, userdata);
}
-void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
+/*** Volume manipulation ***/
- c->get_sink_info_callback = cb;
- c->get_sink_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_tagstruct_puts(t, "");
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c);
-}
-
-void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
+struct pa_operation* pa_context_set_sink_volume_by_index(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
+ struct pa_operation *o;
struct pa_tagstruct *t;
uint32_t tag;
- assert(c);
+ assert(c && index != PA_INVALID_INDEX);
- c->get_source_info_callback = cb;
- c->get_source_info_userdata = userdata;
+ o = pa_operation_new(c, NULL);
+ o->callback = cb;
+ o->userdata = userdata;
- if (!cb)
- return;
-
t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO);
+ pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_VOLUME);
pa_tagstruct_putu32(t, tag = c->ctag++);
pa_tagstruct_putu32(t, index);
pa_tagstruct_puts(t, "");
+ pa_tagstruct_putu32(t, volume);
pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c);
-}
-
-static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, NULL, 0, c->get_client_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_client_info i;
+ pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o);
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.protocol_name) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, &i, 0, c->get_client_info_userdata);
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, NULL, 1, c->get_client_info_userdata);
+ return pa_operation_ref(o);
}
-
-void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
+struct pa_operation* pa_context_set_sink_volume_by_name(struct pa_context *c, const char *name, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
+ struct pa_operation *o;
struct pa_tagstruct *t;
uint32_t tag;
- assert(c);
-
- c->get_client_info_callback = cb;
- c->get_client_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c);
-}
-
-void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
+ assert(c && name);
- c->get_client_info_callback = cb;
- c->get_client_info_userdata = userdata;
+ o = pa_operation_new(c, NULL);
+ o->callback = cb;
+ o->userdata = userdata;
- if (!cb)
- return;
-
t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO_LIST);
+ pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_VOLUME);
pa_tagstruct_putu32(t, tag = c->ctag++);
+ pa_tagstruct_putu32(t, PA_INVALID_INDEX);
+ pa_tagstruct_puts(t, name);
+ pa_tagstruct_putu32(t, volume);
pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c);
-}
-
-static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, NULL, 0, c->get_module_info_userdata);
- return;
- }
+ pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o);
- while (!pa_tagstruct_eof(t)) {
- struct pa_module_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.argument) < 0 ||
- pa_tagstruct_getu32(t, &i.n_used) < 0 ||
- pa_tagstruct_getu32(t, &i.auto_unload) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, &i, 0, c->get_module_info_userdata);
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, NULL, 1, c->get_module_info_userdata);
+ return pa_operation_ref(o);
}
-void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
+struct pa_operation* pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
+ struct pa_operation *o;
struct pa_tagstruct *t;
uint32_t tag;
- assert(c);
+ assert(c && index != PA_INVALID_INDEX);
- c->get_module_info_callback = cb;
- c->get_module_info_userdata = userdata;
+ o = pa_operation_new(c, NULL);
+ o->callback = cb;
+ o->userdata = userdata;
- if (!cb)
- return;
-
t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO);
+ pa_tagstruct_putu32(t, PA_COMMAND_SET_SINK_INPUT_VOLUME);
pa_tagstruct_putu32(t, tag = c->ctag++);
pa_tagstruct_putu32(t, index);
+ pa_tagstruct_putu32(t, volume);
pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c);
-}
+ pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o);
-void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_module_info_callback = cb;
- c->get_module_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c);
+ return pa_operation_ref(o);
}
diff --git a/polyp/polyplib-introspect.h b/polyp/polyplib-introspect.h
index a0dd9f9c..bca752e2 100644
--- a/polyp/polyplib-introspect.h
+++ b/polyp/polyplib-introspect.h
@@ -1,5 +1,5 @@
-#ifndef foopolyplibhfoo
-#define foopolyplibhfoo
+#ifndef foopolyplibintrospecthfoo
+#define foopolyplibintrospecthfoo
/* $Id$ */
@@ -22,61 +22,13 @@
USA.
***/
-#include <sys/types.h>
+#include <inttypes.h>
-#include "sample.h"
-#include "polyplib-def.h"
-#include "mainloop-api.h"
+#include "polyplib-operation.h"
+#include "polyplib-context.h"
+#include "cdecl.h"
-#ifdef __cplusplus
-//extern "C" {
-#endif
-
-struct pa_context;
-struct pa_stream;
-
-struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name);
-void pa_context_unref(struct pa_context *c);
-struct pa_context* pa_context_ref(struct pa_context *c);
-
-int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata);
-int pa_context_drain(struct pa_context *c, void (*complete) (struct pa_context*c, void *userdata), void *userdata);
-void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata);
-
-int pa_context_is_dead(struct pa_context *c);
-int pa_context_is_ready(struct pa_context *c);
-int pa_context_errno(struct pa_context *c);
-
-int pa_context_is_pending(struct pa_context *c);
-
-struct pa_stream* pa_stream_new(struct pa_context *c, enum pa_stream_direction dir, const char *dev, const char *name, const struct pa_sample_spec *ss, const struct pa_buffer_attr *attr, void (*complete) (struct pa_stream*s, int success, void *userdata), void *userdata);
-void pa_stream_unref(struct pa_stream *s);
-struct pa_stream *pa_stream_ref(struct pa_stream *s);
-
-void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata);
-
-void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata);
-
-void pa_stream_set_write_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata);
-void pa_stream_write(struct pa_stream *p, const void *data, size_t length);
-size_t pa_stream_writable_size(struct pa_stream *p);
-
-void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata);
-
-int pa_stream_is_dead(struct pa_stream *p);
-int pa_stream_is_ready(struct pa_stream*p);
-
-void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata);
-
-struct pa_context* pa_stream_get_context(struct pa_stream *p);
-
-uint32_t pa_stream_get_index(struct pa_stream *s);
-
-struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata);
-void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata);
-
-void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
+PA_C_DECL_BEGIN
struct pa_sink_info {
const char *name;
@@ -90,9 +42,9 @@ struct pa_sink_info {
uint32_t latency;
};
-void pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
+struct pa_operation* pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
+struct pa_operation* pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
+struct pa_operation* pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
struct pa_source_info {
const char *name;
@@ -104,9 +56,9 @@ struct pa_source_info {
const char *monitor_of_sink_name;
};
-void pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
+struct pa_operation* pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
+struct pa_operation* pa_context_get_source_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
+struct pa_operation* pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
struct pa_server_info {
const char *user_name;
@@ -116,7 +68,7 @@ struct pa_server_info {
struct pa_sample_spec sample_spec;
};
-void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata);
+struct pa_operation* pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata);
struct pa_module_info {
uint32_t index;
@@ -124,8 +76,8 @@ struct pa_module_info {
uint32_t n_used, auto_unload;
};
-void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata);
+struct pa_operation* pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata);
+struct pa_operation* pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata);
struct pa_client_info {
uint32_t index;
@@ -134,8 +86,8 @@ struct pa_client_info {
const char *protocol_name;
};
-void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata);
+struct pa_operation* pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata);
+struct pa_operation* pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata);
struct pa_sink_input_info {
uint32_t index;
@@ -148,8 +100,8 @@ struct pa_sink_input_info {
uint32_t latency;
};
-void pa_context_get_sink_input_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_input_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata);
+struct pa_operation* pa_context_get_sink_input_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata);
+struct pa_operation* pa_context_get_sink_input_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata);
struct pa_source_output_info {
uint32_t index;
@@ -160,19 +112,20 @@ struct pa_source_output_info {
struct pa_sample_spec sample_spec;
};
-void pa_context_get_source_output_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_output_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata);
+struct pa_operation* pa_context_get_source_output_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata);
+struct pa_operation* pa_context_get_source_output_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_set_sink_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-void pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
+struct pa_operation* pa_context_set_sink_volume_by_index(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
+struct pa_operation* pa_context_set_sink_volume_by_name(struct pa_context *c, const char *name, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
+struct pa_operation* pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-void pa_context_exit(struct pa_context *c);
-void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata);
+struct pa_stat_info {
+ uint32_t memblock_count;
+ uint32_t memblock_total;
+};
-void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata);
+struct pa_operation* pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_stat_info *i, void *userdata), void *userdata);
-#ifdef __cplusplus
-}
-#endif
+PA_C_DECL_END
#endif
diff --git a/polyp/polyplib-operation.c b/polyp/polyplib-operation.c
new file mode 100644
index 00000000..994ac016
--- /dev/null
+++ b/polyp/polyplib-operation.c
@@ -0,0 +1,78 @@
+#include <assert.h>
+
+#include "xmalloc.h"
+#include "polyplib-internal.h"
+#include "polyplib-operation.h"
+
+struct pa_operation *pa_operation_new(struct pa_context *c, struct pa_stream *s) {
+ struct pa_operation *o;
+ assert(c);
+
+ o = pa_xmalloc(sizeof(struct pa_operation));
+ o->ref = 1;
+ o->context = pa_context_ref(c);
+ o->stream = s ? pa_stream_ref(s) : NULL;
+
+ o->state = PA_OPERATION_RUNNING;
+ o->userdata = NULL;
+ o->callback = NULL;
+
+ PA_LLIST_PREPEND(struct pa_operation, o->context->operations, o);
+ return pa_operation_ref(o);
+}
+
+struct pa_operation *pa_operation_ref(struct pa_operation *o) {
+ assert(o && o->ref >= 1);
+ o->ref++;
+ return o;
+}
+
+void pa_operation_unref(struct pa_operation *o) {
+ assert(o && o->ref >= 1);
+
+ if ((--(o->ref)) == 0) {
+ assert(!o->context);
+ assert(!o->stream);
+ free(o);
+ }
+}
+
+static void operation_set_state(struct pa_operation *o, enum pa_operation_state st) {
+ assert(o && o->ref >= 1);
+
+ if (st == o->state)
+ return;
+
+ if (!o->context)
+ return;
+
+ o->state = st;
+
+ if ((o->state == PA_OPERATION_DONE) || (o->state == PA_OPERATION_CANCELED)) {
+ PA_LLIST_REMOVE(struct pa_operation, o->context->operations, o);
+ pa_context_unref(o->context);
+ if (o->stream)
+ pa_stream_unref(o->stream);
+ o->context = NULL;
+ o->stream = NULL;
+ o->callback = NULL;
+ o->userdata = NULL;
+
+ pa_operation_unref(o);
+ }
+}
+
+void pa_operation_cancel(struct pa_operation *o) {
+ assert(o && o->ref >= 1);
+ operation_set_state(o, PA_OPERATION_CANCELED);
+}
+
+void pa_operation_done(struct pa_operation *o) {
+ assert(o && o->ref >= 1);
+ operation_set_state(o, PA_OPERATION_DONE);
+}
+
+enum pa_operation_state pa_operation_get_state(struct pa_operation *o) {
+ assert(o && o->ref >= 1);
+ return o->state;
+}
diff --git a/polyp/polyplib-operation.h b/polyp/polyplib-operation.h
new file mode 100644
index 00000000..7d0adc26
--- /dev/null
+++ b/polyp/polyplib-operation.h
@@ -0,0 +1,56 @@
+#ifndef foopolypliboperationhfoo
+#define foopolypliboperationhfoo
+
+/* $Id$ */
+
+/***
+ This file is part of polypaudio.
+
+ polypaudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2 of the License,
+ or (at your option) any later version.
+
+ polypaudio 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 polypaudio; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+***/
+
+#include "cdecl.h"
+
+/** \file
+ * Asynchronous operations */
+
+PA_C_DECL_BEGIN
+
+enum pa_operation_state {
+ PA_OPERATION_RUNNING, /**< The operation is still running */
+ PA_OPERATION_DONE, /**< The operation has been completed */
+ PA_OPERATION_CANCELED, /**< The operation has been canceled */
+};
+
+/** \struct pa_operation
+ * An asynchronous operation object */
+struct pa_operation;
+
+/** Increase the reference count by one */
+struct pa_operation *pa_operation_ref(struct pa_operation *o);
+
+/** Decrease the reference count by one */
+void pa_operation_unref(struct pa_operation *o);
+
+/** Cancel the operation. Beware! This will not necessarily cancel the execution of the operation on the server side. */
+void pa_operation_cancel(struct pa_operation *o);
+
+/** Return the current status of the operation */
+enum pa_operation_state pa_operation_get_state(struct pa_operation *o);
+
+PA_C_DECL_END
+
+#endif
diff --git a/polyp/polyplib-sample.c b/polyp/polyplib-sample.c
deleted file mode 100644
index 35001d3d..00000000
--- a/polyp/polyplib-sample.c
+++ /dev/null
@@ -1,1550 +0,0 @@
-/* $Id$ */
-
-/***
- This file is part of polypaudio.
-
- polypaudio is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2 of the License,
- or (at your option) any later version.
-
- polypaudio 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 polypaudio; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- USA.
-***/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-
-#include "polyplib.h"
-#include "native-common.h"
-#include "pdispatch.h"
-#include "pstream.h"
-#include "dynarray.h"
-#include "socket-client.h"
-#include "pstream-util.h"
-#include "authkey.h"
-#include "util.h"
-#include "xmalloc.h"
-
-#define DEFAULT_MAXLENGTH 204800
-#define DEFAULT_TLENGTH 10240
-#define DEFAULT_PREBUF 4096
-#define DEFAULT_MINREQ 1024
-#define DEFAULT_FRAGSIZE 1024
-
-#define DEFAULT_TIMEOUT (5*60)
-#define DEFAULT_SERVER "/tmp/polypaudio/native"
-#define DEFAULT_PORT "4713"
-
-struct pa_context {
- char *name;
- struct pa_mainloop_api* mainloop;
- struct pa_socket_client *client;
- struct pa_pstream *pstream;
- struct pa_pdispatch *pdispatch;
- struct pa_dynarray *record_streams, *playback_streams;
- struct pa_stream *first_stream;
- uint32_t ctag;
- uint32_t error;
- enum {
- CONTEXT_UNCONNECTED,
- CONTEXT_CONNECTING,
- CONTEXT_AUTHORIZING,
- CONTEXT_SETTING_NAME,
- CONTEXT_READY,
- CONTEXT_DEAD
- } state;
-
- void (*connect_complete_callback)(struct pa_context*c, int success, void *userdata);
- void *connect_complete_userdata;
-
- void (*drain_complete_callback)(struct pa_context*c, void *userdata);
- void *drain_complete_userdata;
-
- void (*die_callback)(struct pa_context*c, void *userdata);
- void *die_userdata;
-
- void (*stat_callback)(struct pa_context*c, uint32_t count, uint32_t total, void *userdata);
- void *stat_userdata;
-
- void (*play_sample_callback)(struct pa_context*c, int success, void *userdata);
- void *play_sample_userdata;
-
- void (*remove_sample_callback)(struct pa_context*c, int success, void *userdata);
- void *remove_sample_userdata;
-
- void (*get_server_info_callback)(struct pa_context*c, const struct pa_server_info* i, void *userdata);
- void *get_server_info_userdata;
-
- void (*get_sink_info_callback)(struct pa_context*c, const struct pa_sink_info* i, int is_last, void *userdata);
- void *get_sink_info_userdata;
-
- void (*get_source_info_callback)(struct pa_context*c, const struct pa_source_info* i, int is_last, void *userdata);
- void *get_source_info_userdata;
-
- void (*subscribe_callback)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata);
- void *subscribe_userdata;
- enum pa_subscription_mask subscribe_mask;
-
- void (*get_client_info_callback)(struct pa_context*c, const struct pa_client_info* i, int is_last, void *userdata);
- void *get_client_info_userdata;
-
- void (*get_module_info_callback)(struct pa_context*c, const struct pa_module_info* i, int is_last, void *userdata);
- void *get_module_info_userdata;
-
- uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH];
-};
-
-struct pa_stream {
- struct pa_context *context;
- struct pa_stream *next, *previous;
-
- char *name;
- struct pa_buffer_attr buffer_attr;
- struct pa_sample_spec sample_spec;
- uint32_t channel;
- int channel_valid;
- uint32_t device_index;
- enum pa_stream_direction direction;
-
- enum { STREAM_CREATING, STREAM_READY, STREAM_DEAD} state;
- uint32_t requested_bytes;
-
- void (*read_callback)(struct pa_stream *p, const void*data, size_t length, void *userdata);
- void *read_userdata;
-
- void (*write_callback)(struct pa_stream *p, size_t length, void *userdata);
- void *write_userdata;
-
- void (*create_complete_callback)(struct pa_stream *s, int success, void *userdata);
- void *create_complete_userdata;
-
- void (*drain_complete_callback)(struct pa_stream *s, void *userdata);
- void *drain_complete_userdata;
-
- void (*die_callback)(struct pa_stream*c, void *userdata);
- void *die_userdata;
-
- void (*get_latency_callback)(struct pa_stream*c, uint32_t latency, void *userdata);
- void *get_latency_userdata;
-
- void (*finish_sample_callback)(struct pa_stream*c, int success, void *userdata);
- void *finish_sample_userdata;
-};
-
-static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-
-static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = {
- [PA_COMMAND_ERROR] = { NULL },
- [PA_COMMAND_REPLY] = { NULL },
- [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { NULL },
- [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { NULL },
- [PA_COMMAND_CREATE_RECORD_STREAM] = { NULL },
- [PA_COMMAND_DELETE_RECORD_STREAM] = { NULL },
- [PA_COMMAND_EXIT] = { NULL },
- [PA_COMMAND_REQUEST] = { command_request },
- [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { command_playback_stream_killed },
- [PA_COMMAND_RECORD_STREAM_KILLED] = { command_playback_stream_killed },
- [PA_COMMAND_SUBSCRIBE_EVENT] = { command_subscribe_event },
-};
-
-struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) {
- struct pa_context *c;
- assert(mainloop && name);
-
- c = pa_xmalloc(sizeof(struct pa_context));
- c->name = pa_xstrdup(name);
- c->mainloop = mainloop;
- c->client = NULL;
- c->pstream = NULL;
- c->pdispatch = NULL;
- c->playback_streams = pa_dynarray_new();
- assert(c->playback_streams);
- c->record_streams = pa_dynarray_new();
- assert(c->record_streams);
- c->first_stream = NULL;
- c->error = PA_ERROR_OK;
- c->state = CONTEXT_UNCONNECTED;
- c->ctag = 0;
-
- c->connect_complete_callback = NULL;
- c->connect_complete_userdata = NULL;
-
- c->drain_complete_callback = NULL;
- c->drain_complete_userdata = NULL;
-
- c->die_callback = NULL;
- c->die_userdata = NULL;
-
- c->stat_callback = NULL;
- c->stat_userdata = NULL;
-
- c->play_sample_callback = NULL;
- c->play_sample_userdata = NULL;
-
- c->remove_sample_callback = NULL;
- c->remove_sample_userdata = NULL;
-
- c->get_server_info_callback = NULL;
- c->get_server_info_userdata = NULL;
-
- c->get_sink_info_callback = NULL;
- c->get_sink_info_userdata = NULL;
-
- c->get_source_info_callback = NULL;
- c->get_source_info_userdata = NULL;
-
- c->subscribe_callback = NULL;
- c->subscribe_userdata = NULL;
-
- c->get_client_info_callback = NULL;
- c->get_client_info_userdata = NULL;
-
- c->get_module_info_callback = NULL;
- c->get_module_info_userdata = NULL;
-
- pa_check_for_sigpipe();
- return c;
-}
-
-void pa_context_free(struct pa_context *c) {
- assert(c);
-
- while (c->first_stream)
- pa_stream_free(c->first_stream);
-
- if (c->client)
- pa_socket_client_free(c->client);
- if (c->pdispatch)
- pa_pdispatch_free(c->pdispatch);
- if (c->pstream)
- pa_pstream_free(c->pstream);
- if (c->record_streams)
- pa_dynarray_free(c->record_streams, NULL, NULL);
- if (c->playback_streams)
- pa_dynarray_free(c->playback_streams, NULL, NULL);
-
- pa_xfree(c->name);
- pa_xfree(c);
-}
-
-static void stream_dead(struct pa_stream *s) {
- assert(s);
-
- if (s->state == STREAM_DEAD)
- return;
-
- if (s->state == STREAM_READY) {
- s->state = STREAM_DEAD;
- if (s->die_callback)
- s->die_callback(s, s->die_userdata);
- } else
- s->state = STREAM_DEAD;
-}
-
-static void context_dead(struct pa_context *c) {
- struct pa_stream *s;
- assert(c);
-
- if (c->state == CONTEXT_DEAD)
- return;
-
- if (c->pdispatch)
- pa_pdispatch_free(c->pdispatch);
- c->pdispatch = NULL;
-
- if (c->pstream)
- pa_pstream_free(c->pstream);
- c->pstream = NULL;
-
- if (c->client)
- pa_socket_client_free(c->client);
- c->client = NULL;
-
- for (s = c->first_stream; s; s = s->next)
- stream_dead(s);
-
- if (c->state == CONTEXT_READY) {
- c->state = CONTEXT_DEAD;
- if (c->die_callback)
- c->die_callback(c, c->die_userdata);
- } else
- c->state = CONTEXT_DEAD;
-}
-
-static void pstream_die_callback(struct pa_pstream *p, void *userdata) {
- struct pa_context *c = userdata;
- assert(p && c);
- c->error = PA_ERROR_CONNECTIONTERMINATED;
- context_dead(c);
-}
-
-static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) {
- struct pa_context *c = userdata;
- assert(p && packet && c);
-
- if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) {
- fprintf(stderr, "polyp.c: invalid packet.\n");
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- }
-}
-
-static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_stream *s;
- assert(p && chunk && c && chunk->memblock && chunk->memblock->data);
-
- if (!(s = pa_dynarray_get(c->record_streams, channel)))
- return;
-
- if (s->read_callback)
- s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata);
-}
-
-static int handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t) {
- assert(c && t);
-
- if (command == PA_COMMAND_ERROR) {
- if (pa_tagstruct_getu32(t, &c->error) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- return -1;
- }
-
- return 0;
- }
-
- c->error = (command == PA_COMMAND_TIMEOUT) ? PA_ERROR_TIMEOUT : PA_ERROR_INTERNAL;
- return -1;
-}
-
-static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c && (c->state == CONTEXT_AUTHORIZING || c->state == CONTEXT_SETTING_NAME));
-
- if (command != PA_COMMAND_REPLY) {
- handle_error(c, command, t);
- context_dead(c);
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 0, c->connect_complete_userdata);
-
- return;
- }
-
- if (c->state == CONTEXT_AUTHORIZING) {
- struct pa_tagstruct *t;
- c->state = CONTEXT_SETTING_NAME;
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_SET_NAME);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, c->name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c);
- } else {
- assert(c->state == CONTEXT_SETTING_NAME);
-
- c->state = CONTEXT_READY;
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 1, c->connect_complete_userdata);
- }
-
- return;
-}
-
-static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(client && c && c->state == CONTEXT_CONNECTING);
-
- pa_socket_client_free(client);
- c->client = NULL;
-
- if (!io) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- context_dead(c);
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 0, c->connect_complete_userdata);
-
- return;
- }
-
- c->pstream = pa_pstream_new(c->mainloop, io);
- assert(c->pstream);
- pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c);
- pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c);
- pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c);
-
- c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX);
- assert(c->pdispatch);
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_AUTH);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_put_arbitrary(t, c->auth_cookie, sizeof(c->auth_cookie));
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c);
- c->state = CONTEXT_AUTHORIZING;
-}
-
-static struct sockaddr *resolve_server(const char *server, size_t *len) {
- struct sockaddr *sa;
- struct addrinfo hints, *result = NULL;
- char *port;
- assert(server && len);
-
- if ((port = strrchr(server, ':')))
- port++;
- if (!port)
- port = DEFAULT_PORT;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = 0;
-
- if (getaddrinfo(server, port, &hints, &result) != 0)
- return NULL;
- assert(result);
-
- sa = pa_xmalloc(*len = result->ai_addrlen);
- memcpy(sa, result->ai_addr, *len);
-
- freeaddrinfo(result);
-
- return sa;
-}
-
-int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata) {
- assert(c && c->state == CONTEXT_UNCONNECTED);
-
- if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE, c->auth_cookie, sizeof(c->auth_cookie)) < 0) {
- c->error = PA_ERROR_AUTHKEY;
- return -1;
- }
-
- if (!server)
- if (!(server = getenv("POLYP_SERVER")))
- server = DEFAULT_SERVER;
-
- assert(!c->client);
-
- if (*server == '/') {
- if (!(c->client = pa_socket_client_new_unix(c->mainloop, server))) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- return -1;
- }
- } else {
- struct sockaddr* sa;
- size_t sa_len;
-
- if (!(sa = resolve_server(server, &sa_len))) {
- c->error = PA_ERROR_INVALIDSERVER;
- return -1;
- }
-
- c->client = pa_socket_client_new_sockaddr(c->mainloop, sa, sa_len);
- pa_xfree(sa);
-
- if (!c->client) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- return -1;
- }
- }
-
- c->connect_complete_callback = complete;
- c->connect_complete_userdata = userdata;
-
- pa_socket_client_set_callback(c->client, on_connection, c);
- c->state = CONTEXT_CONNECTING;
-
- return 0;
-}
-
-int pa_context_is_dead(struct pa_context *c) {
- assert(c);
- return c->state == CONTEXT_DEAD;
-}
-
-int pa_context_is_ready(struct pa_context *c) {
- assert(c);
- return c->state == CONTEXT_READY;
-}
-
-int pa_context_errno(struct pa_context *c) {
- assert(c);
- return c->error;
-}
-
-void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata) {
- assert(c);
- c->die_callback = cb;
- c->die_userdata = userdata;
-}
-
-static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_stream *s;
- uint32_t channel;
- assert(pd && (command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED) && t && c);
-
- if (pa_tagstruct_getu32(t, &channel) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel)))
- return;
-
- c->error = PA_ERROR_KILLED;
- stream_dead(s);
-}
-
-static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s;
- struct pa_context *c = userdata;
- uint32_t bytes, channel;
- assert(pd && command == PA_COMMAND_REQUEST && t && c);
-
- if (pa_tagstruct_getu32(t, &channel) < 0 ||
- pa_tagstruct_getu32(t, &bytes) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (!(s = pa_dynarray_get(c->playback_streams, channel)))
- return;
-
- if (s->state != STREAM_READY)
- return;
-
- s->requested_bytes += bytes;
-
- if (s->requested_bytes && s->write_callback)
- s->write_callback(s, s->requested_bytes, s->write_userdata);
-}
-
-static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s && s->state == STREAM_CREATING);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- stream_dead(s);
- if (s->create_complete_callback)
- s->create_complete_callback(s, 0, s->create_complete_userdata);
-
- return;
- }
-
- if (pa_tagstruct_getu32(t, &s->channel) < 0 ||
- ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) ||
- !pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- s->channel_valid = 1;
- pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s);
-
- s->state = STREAM_READY;
- if (s->create_complete_callback)
- s->create_complete_callback(s, 1, s->create_complete_userdata);
-}
-
-static void create_stream(struct pa_stream *s, const char *dev) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(s);
-
- s->state = STREAM_CREATING;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM);
- pa_tagstruct_putu32(t, tag = s->context->ctag++);
- pa_tagstruct_puts(t, s->name);
- pa_tagstruct_put_sample_spec(t, &s->sample_spec);
- pa_tagstruct_putu32(t, (uint32_t) -1);
- pa_tagstruct_puts(t, dev ? dev : "");
- pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
- if (s->direction == PA_STREAM_PLAYBACK) {
- pa_tagstruct_putu32(t, s->buffer_attr.tlength);
- pa_tagstruct_putu32(t, s->buffer_attr.prebuf);
- pa_tagstruct_putu32(t, s->buffer_attr.minreq);
- } else
- pa_tagstruct_putu32(t, s->buffer_attr.fragsize);
-
- pa_pstream_send_tagstruct(s->context->pstream, t);
- pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s);
-}
-
-static struct pa_stream *internal_stream_new(struct pa_context *c) {
- struct pa_stream *s;
-
- s = pa_xmalloc(sizeof(struct pa_stream));
- s->context = c;
-
- s->read_callback = NULL;
- s->read_userdata = NULL;
- s->write_callback = NULL;
- s->write_userdata = NULL;
- s->die_callback = NULL;
- s->die_userdata = NULL;
- s->create_complete_callback = NULL;
- s->create_complete_userdata = NULL;
- s->get_latency_callback = NULL;
- s->get_latency_userdata = NULL;
- s->finish_sample_callback = NULL;
- s->finish_sample_userdata = NULL;
-
- s->name = NULL;
- s->state = STREAM_CREATING;
- s->requested_bytes = 0;
- s->channel = 0;
- s->channel_valid = 0;
- s->device_index = (uint32_t) -1;
-
- memset(&s->buffer_attr, 0, sizeof(s->buffer_attr));
-
- s->next = c->first_stream;
- if (s->next)
- s->next->previous = s;
- s->previous = NULL;
- c->first_stream = s;
-
- return s;
-}
-
-struct pa_stream* pa_stream_new(
- struct pa_context *c,
- enum pa_stream_direction dir,
- const char *dev,
- const char *name,
- const struct pa_sample_spec *ss,
- const struct pa_buffer_attr *attr,
- void (*complete) (struct pa_stream*s, int success, void *userdata),
- void *userdata) {
-
- struct pa_stream *s;
-
- assert(c && name && ss && c->state == CONTEXT_READY && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD));
-
- s = internal_stream_new(c);
- assert(s);
-
- s->create_complete_callback = complete;
- s->create_complete_userdata = userdata;
- s->name = pa_xstrdup(name);
- s->state = STREAM_CREATING;
- s->direction = dir;
- s->sample_spec = *ss;
- if (attr)
- s->buffer_attr = *attr;
- else {
- s->buffer_attr.maxlength = DEFAULT_MAXLENGTH;
- s->buffer_attr.tlength = DEFAULT_TLENGTH;
- s->buffer_attr.prebuf = DEFAULT_PREBUF;
- s->buffer_attr.minreq = DEFAULT_MINREQ;
- s->buffer_attr.fragsize = DEFAULT_FRAGSIZE;
- }
-
- create_stream(s, dev);
-
- return s;
-}
-
-void pa_stream_free(struct pa_stream *s) {
- assert(s && s->context);
-
- if (s->context->pdispatch)
- pa_pdispatch_unregister_reply(s->context->pdispatch, s);
-
- pa_xfree(s->name);
-
- if (s->channel_valid && s->context->state == CONTEXT_READY) {
- struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM :
- (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM));
- pa_tagstruct_putu32(t, s->context->ctag++);
- pa_tagstruct_putu32(t, s->channel);
- pa_pstream_send_tagstruct(s->context->pstream, t);
- }
-
- if (s->channel_valid)
- pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL);
-
- if (s->next)
- s->next->previous = s->previous;
- if (s->previous)
- s->previous->next = s->next;
- else
- s->context->first_stream = s->next;
-
- pa_xfree(s);
-}
-
-void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) {
- s->write_callback = cb;
- s->write_userdata = userdata;
-}
-
-void pa_stream_write(struct pa_stream *s, const void *data, size_t length) {
- struct pa_memchunk chunk;
- assert(s && s->context && data && length && s->state == STREAM_READY);
-
- chunk.memblock = pa_memblock_new(length);
- assert(chunk.memblock && chunk.memblock->data);
- memcpy(chunk.memblock->data, data, length);
- chunk.index = 0;
- chunk.length = length;
-
- pa_pstream_send_memblock(s->context->pstream, s->channel, 0, &chunk);
- pa_memblock_unref(chunk.memblock);
-
- /*fprintf(stderr, "Sent %u bytes\n", length);*/
-
- if (length < s->requested_bytes)
- s->requested_bytes -= length;
- else
- s->requested_bytes = 0;
-}
-
-size_t pa_stream_writable_size(struct pa_stream *s) {
- assert(s && s->state == STREAM_READY);
- return s->requested_bytes;
-}
-
-void pa_stream_set_read_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) {
- assert(s && cb);
- s->read_callback = cb;
- s->read_userdata = userdata;
-}
-
-int pa_stream_is_dead(struct pa_stream *s) {
- return s->state == STREAM_DEAD;
-}
-
-int pa_stream_is_ready(struct pa_stream*s) {
- return s->state == STREAM_READY;
-}
-
-void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata) {
- assert(s);
- s->die_callback = cb;
- s->die_userdata = userdata;
-}
-
-int pa_context_is_pending(struct pa_context *c) {
- assert(c);
-
- if (c->state != CONTEXT_READY)
- return 0;
-
- return pa_pstream_is_pending(c->pstream) || pa_pdispatch_is_pending(c->pdispatch);
-}
-
-struct pa_context* pa_stream_get_context(struct pa_stream *p) {
- assert(p);
- return p->context;
-}
-
-static void set_dispatch_callbacks(struct pa_context *c);
-
-static void pdispatch_drain_callback(struct pa_pdispatch*pd, void *userdata) {
- set_dispatch_callbacks(userdata);
-}
-
-static void pstream_drain_callback(struct pa_pstream *s, void *userdata) {
- set_dispatch_callbacks(userdata);
-}
-
-static void set_dispatch_callbacks(struct pa_context *c) {
- assert(c && c->state == CONTEXT_READY);
-
- pa_pstream_set_drain_callback(c->pstream, NULL, NULL);
- pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL);
-
- if (pa_pdispatch_is_pending(c->pdispatch)) {
- pa_pdispatch_set_drain_callback(c->pdispatch, pdispatch_drain_callback, c);
- return;
- }
-
- if (pa_pstream_is_pending(c->pstream)) {
- pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c);
- return;
- }
-
- assert(c->drain_complete_callback);
- c->drain_complete_callback(c, c->drain_complete_userdata);
-}
-
-int pa_context_drain(
- struct pa_context *c,
- void (*complete) (struct pa_context*c, void *userdata),
- void *userdata) {
-
- assert(c && c->state == CONTEXT_READY);
-
- if (complete == NULL) {
- c->drain_complete_callback = NULL;
- pa_pstream_set_drain_callback(c->pstream, NULL, NULL);
- pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL);
- return 0;
- }
-
- if (!pa_context_is_pending(c))
- return -1;
-
- c->drain_complete_callback = complete;
- c->drain_complete_userdata = userdata;
-
- set_dispatch_callbacks(c);
-
- return 0;
-}
-
-static void stream_drain_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- stream_dead(s);
- return;
- }
-
- if (s->state != STREAM_READY)
- return;
-
- if (!pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->drain_complete_callback) {
- void (*temp) (struct pa_stream*s, void *userdata) = s->drain_complete_callback;
- s->drain_complete_callback = NULL;
- temp(s, s->drain_complete_userdata);
- }
-}
-
-
-void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(s && s->state == STREAM_READY);
-
- if (!complete) {
- s->drain_complete_callback = NULL;
- return;
- }
-
- s->drain_complete_callback = complete;
- s->drain_complete_userdata = userdata;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, PA_COMMAND_DRAIN_PLAYBACK_STREAM);
- pa_tagstruct_putu32(t, tag = s->context->ctag++);
- pa_tagstruct_putu32(t, s->channel);
- pa_pstream_send_tagstruct(s->context->pstream, t);
- pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_drain_callback, s);
-}
-
-void pa_context_exit(struct pa_context *c) {
- struct pa_tagstruct *t;
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_EXIT);
- pa_tagstruct_putu32(t, c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
-}
-
-static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- uint32_t total, count;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->stat_callback)
- c->stat_callback(c, (uint32_t) -1, (uint32_t) -1, c->stat_userdata);
- return;
- }
-
- if (pa_tagstruct_getu32(t, &count) < 0 ||
- pa_tagstruct_getu32(t, &total) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->stat_callback)
- c->stat_callback(c, count, total, c->stat_userdata);
-}
-
-void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata) {
- uint32_t tag;
- struct pa_tagstruct *t;
-
- c->stat_callback = cb;
- c->stat_userdata = userdata;
-
- if (cb == NULL)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_STAT);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_stat_callback, c);
-}
-
-static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- uint32_t latency;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- if (s->get_latency_callback)
- s->get_latency_callback(s, (uint32_t) -1, s->get_latency_userdata);
- return;
- }
-
- if (pa_tagstruct_getu32(t, &latency) < 0 ||
- !pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->get_latency_callback)
- s->get_latency_callback(s, latency, s->get_latency_userdata);
-}
-
-void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata) {
- uint32_t tag;
- struct pa_tagstruct *t;
-
- p->get_latency_callback = cb;
- p->get_latency_userdata = userdata;
-
- if (cb == NULL)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY);
- pa_tagstruct_putu32(t, tag = p->context->ctag++);
- pa_tagstruct_putu32(t, p->channel);
- pa_pstream_send_tagstruct(p->context->pstream, t);
- pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, p);
-}
-
-struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) {
- struct pa_stream *s;
- struct pa_tagstruct *t;
- uint32_t tag;
-
- s = internal_stream_new(c);
- assert(s);
-
- s->create_complete_callback = cb;
- s->create_complete_userdata = userdata;
- s->name = pa_xstrdup(name);
- s->state = STREAM_CREATING;
- s->direction = PA_STREAM_UPLOAD;
- s->sample_spec = *ss;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_CREATE_UPLOAD_STREAM);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, name);
- pa_tagstruct_put_sample_spec(t, ss);
- pa_tagstruct_putu32(t, length);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s);
-
- return s;
-}
-
-static void stream_finish_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- if (s->finish_sample_callback)
- s->finish_sample_callback(s, 0, s->finish_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->finish_sample_callback)
- s->finish_sample_callback(s, 1, s->finish_sample_userdata);
-}
-
-void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(p);
-
- p->finish_sample_callback = cb;
- p->finish_sample_userdata = userdata;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_FINISH_UPLOAD_STREAM);
- pa_tagstruct_putu32(t, tag = p->context->ctag++);
- pa_tagstruct_putu32(t, p->channel);
- pa_pstream_send_tagstruct(p->context->pstream, t);
- pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_finish_sample_callback, p);
-}
-
-static void context_play_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->play_sample_callback)
- c->play_sample_callback(c, 0, c->play_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->play_sample_callback)
- c->play_sample_callback(c, 1, c->play_sample_userdata);
-}
-
-void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c && name && *name && (!dev || *dev));
-
- c->play_sample_callback = cb;
- c->play_sample_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_PLAY_SAMPLE);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, (uint32_t) -1);
- pa_tagstruct_puts(t, dev ? dev : "");
- pa_tagstruct_putu32(t, volume);
- pa_tagstruct_puts(t, name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_play_sample_callback, c);
-}
-
-static void context_remove_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->remove_sample_callback)
- c->remove_sample_callback(c, 0, c->remove_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->remove_sample_callback)
- c->remove_sample_callback(c, 1, c->remove_sample_userdata);
-}
-
-void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c && name);
-
- c->remove_sample_callback = cb;
- c->remove_sample_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_SAMPLE);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_remove_sample_callback, c);
-}
-
-static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_server_info i;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_server_info_callback)
- c->get_server_info_callback(c, NULL, c->get_server_info_userdata);
- return;
- }
-
- if (pa_tagstruct_gets(t, &i.server_name) < 0 ||
- pa_tagstruct_gets(t, &i.server_version) < 0 ||
- pa_tagstruct_gets(t, &i.user_name) < 0 ||
- pa_tagstruct_gets(t, &i.host_name) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_server_info_callback)
- c->get_server_info_callback(c, &i, c->get_server_info_userdata);
-}
-
-void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_server_info_callback = cb;
- c->get_server_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SERVER_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_server_info_callback, c);
-}
-
-static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, NULL, 0, c->get_sink_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_sink_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.description) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
- pa_tagstruct_getu32(t, &i.volume) < 0 ||
- pa_tagstruct_getu32(t, &i.monitor_source) < 0 ||
- pa_tagstruct_gets(t, &i.monitor_source_name) < 0 ||
- pa_tagstruct_getu32(t, &i.latency) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, &i, 0, c->get_sink_info_userdata);
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, NULL, 1, c->get_sink_info_userdata);
-}
-
-void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_sink_info_callback = cb;
- c->get_sink_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c);
-}
-
-static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, NULL, 0, c->get_source_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_source_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.description) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
- pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 ||
- pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, &i, 0, c->get_source_info_userdata);
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, NULL, 1, c->get_source_info_userdata);
-}
-
-void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_source_info_callback = cb;
- c->get_source_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c);
-}
-
-void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- assert(c);
-
- c->subscribe_callback = cb;
- c->subscribe_userdata = userdata;
- c->subscribe_mask = m;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE);
- pa_tagstruct_putu32(t, c->ctag++);
- pa_tagstruct_putu32(t, cb ? m : 0);
- pa_pstream_send_tagstruct(c->pstream, t);
-}
-
-static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- enum pa_subscription_event_type e;
- uint32_t index;
- assert(pd && command == PA_COMMAND_SUBSCRIBE_EVENT && t && c);
-
- if (pa_tagstruct_getu32(t, &e) < 0 ||
- pa_tagstruct_getu32(t, &index) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (pa_subscription_match_flags(c->subscribe_mask, e) && c->subscribe_callback)
- c->subscribe_callback(c, e, index, c->subscribe_userdata);
-}
-
-void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_sink_info_callback = cb;
- c->get_sink_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_tagstruct_puts(t, "");
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c);
-}
-
-void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_source_info_callback = cb;
- c->get_source_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_tagstruct_puts(t, "");
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c);
-}
-
-static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, NULL, 0, c->get_client_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_client_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.protocol_name) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, &i, 0, c->get_client_info_userdata);
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, NULL, 1, c->get_client_info_userdata);
-}
-
-
-void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_client_info_callback = cb;
- c->get_client_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c);
-}
-
-void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_client_info_callback = cb;
- c->get_client_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c);
-}
-
-static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, NULL, 0, c->get_module_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_module_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.argument) < 0 ||
- pa_tagstruct_getu32(t, &i.n_used) < 0 ||
- pa_tagstruct_getu32(t, &i.auto_unload) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, &i, 0, c->get_module_info_userdata);
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, NULL, 1, c->get_module_info_userdata);
-}
-
-void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_module_info_callback = cb;
- c->get_module_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c);
-}
-
-void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_module_info_callback = cb;
- c->get_module_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c);
-}
diff --git a/polyp/polyplib-sample.h b/polyp/polyplib-sample.h
deleted file mode 100644
index a0dd9f9c..00000000
--- a/polyp/polyplib-sample.h
+++ /dev/null
@@ -1,178 +0,0 @@
-#ifndef foopolyplibhfoo
-#define foopolyplibhfoo
-
-/* $Id$ */
-
-/***
- This file is part of polypaudio.
-
- polypaudio is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2 of the License,
- or (at your option) any later version.
-
- polypaudio 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 polypaudio; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- USA.
-***/
-
-#include <sys/types.h>
-
-#include "sample.h"
-#include "polyplib-def.h"
-#include "mainloop-api.h"
-
-#ifdef __cplusplus
-//extern "C" {
-#endif
-
-struct pa_context;
-struct pa_stream;
-
-struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name);
-void pa_context_unref(struct pa_context *c);
-struct pa_context* pa_context_ref(struct pa_context *c);
-
-int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata);
-int pa_context_drain(struct pa_context *c, void (*complete) (struct pa_context*c, void *userdata), void *userdata);
-void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata);
-
-int pa_context_is_dead(struct pa_context *c);
-int pa_context_is_ready(struct pa_context *c);
-int pa_context_errno(struct pa_context *c);
-
-int pa_context_is_pending(struct pa_context *c);
-
-struct pa_stream* pa_stream_new(struct pa_context *c, enum pa_stream_direction dir, const char *dev, const char *name, const struct pa_sample_spec *ss, const struct pa_buffer_attr *attr, void (*complete) (struct pa_stream*s, int success, void *userdata), void *userdata);
-void pa_stream_unref(struct pa_stream *s);
-struct pa_stream *pa_stream_ref(struct pa_stream *s);
-
-void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata);
-
-void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata);
-
-void pa_stream_set_write_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata);
-void pa_stream_write(struct pa_stream *p, const void *data, size_t length);
-size_t pa_stream_writable_size(struct pa_stream *p);
-
-void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata);
-
-int pa_stream_is_dead(struct pa_stream *p);
-int pa_stream_is_ready(struct pa_stream*p);
-
-void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata);
-
-struct pa_context* pa_stream_get_context(struct pa_stream *p);
-
-uint32_t pa_stream_get_index(struct pa_stream *s);
-
-struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata);
-void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata);
-
-void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-
-struct pa_sink_info {
- const char *name;
- uint32_t index;
- const char *description;
- struct pa_sample_spec sample_spec;
- uint32_t owner_module;
- uint32_t volume;
- uint32_t monitor_source;
- const char *monitor_source_name;
- uint32_t latency;
-};
-
-void pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-
-struct pa_source_info {
- const char *name;
- uint32_t index;
- const char *description;
- struct pa_sample_spec sample_spec;
- uint32_t owner_module;
- uint32_t monitor_of_sink;
- const char *monitor_of_sink_name;
-};
-
-void pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-
-struct pa_server_info {
- const char *user_name;
- const char *host_name;
- const char *server_version;
- const char *server_name;
- struct pa_sample_spec sample_spec;
-};
-
-void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata);
-
-struct pa_module_info {
- uint32_t index;
- const char*name, *argument;
- uint32_t n_used, auto_unload;
-};
-
-void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata);
-
-struct pa_client_info {
- uint32_t index;
- const char *name;
- uint32_t owner_module;
- const char *protocol_name;
-};
-
-void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata);
-
-struct pa_sink_input_info {
- uint32_t index;
- const char *name;
- uint32_t owner_module;
- uint32_t owner_client;
- uint32_t sink;
- struct pa_sample_spec sample_spec;
- uint32_t volume;
- uint32_t latency;
-};
-
-void pa_context_get_sink_input_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_input_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata);
-
-struct pa_source_output_info {
- uint32_t index;
- const char *name;
- uint32_t owner_module;
- uint32_t owner_client;
- uint32_t source;
- struct pa_sample_spec sample_spec;
-};
-
-void pa_context_get_source_output_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_output_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata);
-
-void pa_context_set_sink_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-void pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-
-void pa_context_exit(struct pa_context *c);
-void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata);
-
-void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/polyp/polyplib-scache.c b/polyp/polyplib-scache.c
index 35001d3d..8215eaec 100644
--- a/polyp/polyplib-scache.c
+++ b/polyp/polyplib-scache.c
@@ -23,1083 +23,73 @@
#include <config.h>
#endif
-#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
+#include <stdio.h>
#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include "polyplib.h"
-#include "native-common.h"
-#include "pdispatch.h"
-#include "pstream.h"
-#include "dynarray.h"
-#include "socket-client.h"
+#include "polyplib-scache.h"
+#include "polyplib-internal.h"
#include "pstream-util.h"
-#include "authkey.h"
-#include "util.h"
-#include "xmalloc.h"
-
-#define DEFAULT_MAXLENGTH 204800
-#define DEFAULT_TLENGTH 10240
-#define DEFAULT_PREBUF 4096
-#define DEFAULT_MINREQ 1024
-#define DEFAULT_FRAGSIZE 1024
-
-#define DEFAULT_TIMEOUT (5*60)
-#define DEFAULT_SERVER "/tmp/polypaudio/native"
-#define DEFAULT_PORT "4713"
-
-struct pa_context {
- char *name;
- struct pa_mainloop_api* mainloop;
- struct pa_socket_client *client;
- struct pa_pstream *pstream;
- struct pa_pdispatch *pdispatch;
- struct pa_dynarray *record_streams, *playback_streams;
- struct pa_stream *first_stream;
- uint32_t ctag;
- uint32_t error;
- enum {
- CONTEXT_UNCONNECTED,
- CONTEXT_CONNECTING,
- CONTEXT_AUTHORIZING,
- CONTEXT_SETTING_NAME,
- CONTEXT_READY,
- CONTEXT_DEAD
- } state;
-
- void (*connect_complete_callback)(struct pa_context*c, int success, void *userdata);
- void *connect_complete_userdata;
-
- void (*drain_complete_callback)(struct pa_context*c, void *userdata);
- void *drain_complete_userdata;
-
- void (*die_callback)(struct pa_context*c, void *userdata);
- void *die_userdata;
-
- void (*stat_callback)(struct pa_context*c, uint32_t count, uint32_t total, void *userdata);
- void *stat_userdata;
-
- void (*play_sample_callback)(struct pa_context*c, int success, void *userdata);
- void *play_sample_userdata;
-
- void (*remove_sample_callback)(struct pa_context*c, int success, void *userdata);
- void *remove_sample_userdata;
-
- void (*get_server_info_callback)(struct pa_context*c, const struct pa_server_info* i, void *userdata);
- void *get_server_info_userdata;
-
- void (*get_sink_info_callback)(struct pa_context*c, const struct pa_sink_info* i, int is_last, void *userdata);
- void *get_sink_info_userdata;
-
- void (*get_source_info_callback)(struct pa_context*c, const struct pa_source_info* i, int is_last, void *userdata);
- void *get_source_info_userdata;
-
- void (*subscribe_callback)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata);
- void *subscribe_userdata;
- enum pa_subscription_mask subscribe_mask;
-
- void (*get_client_info_callback)(struct pa_context*c, const struct pa_client_info* i, int is_last, void *userdata);
- void *get_client_info_userdata;
-
- void (*get_module_info_callback)(struct pa_context*c, const struct pa_module_info* i, int is_last, void *userdata);
- void *get_module_info_userdata;
-
- uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH];
-};
-
-struct pa_stream {
- struct pa_context *context;
- struct pa_stream *next, *previous;
-
- char *name;
- struct pa_buffer_attr buffer_attr;
- struct pa_sample_spec sample_spec;
- uint32_t channel;
- int channel_valid;
- uint32_t device_index;
- enum pa_stream_direction direction;
-
- enum { STREAM_CREATING, STREAM_READY, STREAM_DEAD} state;
- uint32_t requested_bytes;
-
- void (*read_callback)(struct pa_stream *p, const void*data, size_t length, void *userdata);
- void *read_userdata;
-
- void (*write_callback)(struct pa_stream *p, size_t length, void *userdata);
- void *write_userdata;
-
- void (*create_complete_callback)(struct pa_stream *s, int success, void *userdata);
- void *create_complete_userdata;
-
- void (*drain_complete_callback)(struct pa_stream *s, void *userdata);
- void *drain_complete_userdata;
-
- void (*die_callback)(struct pa_stream*c, void *userdata);
- void *die_userdata;
-
- void (*get_latency_callback)(struct pa_stream*c, uint32_t latency, void *userdata);
- void *get_latency_userdata;
-
- void (*finish_sample_callback)(struct pa_stream*c, int success, void *userdata);
- void *finish_sample_userdata;
-};
-
-static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-
-static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = {
- [PA_COMMAND_ERROR] = { NULL },
- [PA_COMMAND_REPLY] = { NULL },
- [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { NULL },
- [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { NULL },
- [PA_COMMAND_CREATE_RECORD_STREAM] = { NULL },
- [PA_COMMAND_DELETE_RECORD_STREAM] = { NULL },
- [PA_COMMAND_EXIT] = { NULL },
- [PA_COMMAND_REQUEST] = { command_request },
- [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { command_playback_stream_killed },
- [PA_COMMAND_RECORD_STREAM_KILLED] = { command_playback_stream_killed },
- [PA_COMMAND_SUBSCRIBE_EVENT] = { command_subscribe_event },
-};
-
-struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) {
- struct pa_context *c;
- assert(mainloop && name);
-
- c = pa_xmalloc(sizeof(struct pa_context));
- c->name = pa_xstrdup(name);
- c->mainloop = mainloop;
- c->client = NULL;
- c->pstream = NULL;
- c->pdispatch = NULL;
- c->playback_streams = pa_dynarray_new();
- assert(c->playback_streams);
- c->record_streams = pa_dynarray_new();
- assert(c->record_streams);
- c->first_stream = NULL;
- c->error = PA_ERROR_OK;
- c->state = CONTEXT_UNCONNECTED;
- c->ctag = 0;
- c->connect_complete_callback = NULL;
- c->connect_complete_userdata = NULL;
-
- c->drain_complete_callback = NULL;
- c->drain_complete_userdata = NULL;
-
- c->die_callback = NULL;
- c->die_userdata = NULL;
-
- c->stat_callback = NULL;
- c->stat_userdata = NULL;
-
- c->play_sample_callback = NULL;
- c->play_sample_userdata = NULL;
-
- c->remove_sample_callback = NULL;
- c->remove_sample_userdata = NULL;
-
- c->get_server_info_callback = NULL;
- c->get_server_info_userdata = NULL;
-
- c->get_sink_info_callback = NULL;
- c->get_sink_info_userdata = NULL;
-
- c->get_source_info_callback = NULL;
- c->get_source_info_userdata = NULL;
-
- c->subscribe_callback = NULL;
- c->subscribe_userdata = NULL;
-
- c->get_client_info_callback = NULL;
- c->get_client_info_userdata = NULL;
-
- c->get_module_info_callback = NULL;
- c->get_module_info_userdata = NULL;
-
- pa_check_for_sigpipe();
- return c;
-}
-
-void pa_context_free(struct pa_context *c) {
- assert(c);
-
- while (c->first_stream)
- pa_stream_free(c->first_stream);
-
- if (c->client)
- pa_socket_client_free(c->client);
- if (c->pdispatch)
- pa_pdispatch_free(c->pdispatch);
- if (c->pstream)
- pa_pstream_free(c->pstream);
- if (c->record_streams)
- pa_dynarray_free(c->record_streams, NULL, NULL);
- if (c->playback_streams)
- pa_dynarray_free(c->playback_streams, NULL, NULL);
-
- pa_xfree(c->name);
- pa_xfree(c);
-}
-
-static void stream_dead(struct pa_stream *s) {
- assert(s);
-
- if (s->state == STREAM_DEAD)
- return;
-
- if (s->state == STREAM_READY) {
- s->state = STREAM_DEAD;
- if (s->die_callback)
- s->die_callback(s, s->die_userdata);
- } else
- s->state = STREAM_DEAD;
-}
-
-static void context_dead(struct pa_context *c) {
- struct pa_stream *s;
- assert(c);
-
- if (c->state == CONTEXT_DEAD)
- return;
-
- if (c->pdispatch)
- pa_pdispatch_free(c->pdispatch);
- c->pdispatch = NULL;
-
- if (c->pstream)
- pa_pstream_free(c->pstream);
- c->pstream = NULL;
-
- if (c->client)
- pa_socket_client_free(c->client);
- c->client = NULL;
-
- for (s = c->first_stream; s; s = s->next)
- stream_dead(s);
-
- if (c->state == CONTEXT_READY) {
- c->state = CONTEXT_DEAD;
- if (c->die_callback)
- c->die_callback(c, c->die_userdata);
- } else
- c->state = CONTEXT_DEAD;
-}
-
-static void pstream_die_callback(struct pa_pstream *p, void *userdata) {
- struct pa_context *c = userdata;
- assert(p && c);
- c->error = PA_ERROR_CONNECTIONTERMINATED;
- context_dead(c);
-}
-
-static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) {
- struct pa_context *c = userdata;
- assert(p && packet && c);
-
- if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) {
- fprintf(stderr, "polyp.c: invalid packet.\n");
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- }
-}
-
-static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_stream *s;
- assert(p && chunk && c && chunk->memblock && chunk->memblock->data);
-
- if (!(s = pa_dynarray_get(c->record_streams, channel)))
- return;
-
- if (s->read_callback)
- s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata);
-}
-
-static int handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t) {
- assert(c && t);
-
- if (command == PA_COMMAND_ERROR) {
- if (pa_tagstruct_getu32(t, &c->error) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- return -1;
- }
-
- return 0;
- }
-
- c->error = (command == PA_COMMAND_TIMEOUT) ? PA_ERROR_TIMEOUT : PA_ERROR_INTERNAL;
- return -1;
-}
-
-static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c && (c->state == CONTEXT_AUTHORIZING || c->state == CONTEXT_SETTING_NAME));
-
- if (command != PA_COMMAND_REPLY) {
- handle_error(c, command, t);
- context_dead(c);
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 0, c->connect_complete_userdata);
-
- return;
- }
-
- if (c->state == CONTEXT_AUTHORIZING) {
- struct pa_tagstruct *t;
- c->state = CONTEXT_SETTING_NAME;
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_SET_NAME);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, c->name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c);
- } else {
- assert(c->state == CONTEXT_SETTING_NAME);
-
- c->state = CONTEXT_READY;
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 1, c->connect_complete_userdata);
- }
-
- return;
-}
-
-static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) {
- struct pa_context *c = userdata;
+void pa_stream_connect_upload(struct pa_stream *s, size_t length) {
struct pa_tagstruct *t;
uint32_t tag;
- assert(client && c && c->state == CONTEXT_CONNECTING);
-
- pa_socket_client_free(client);
- c->client = NULL;
-
- if (!io) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- context_dead(c);
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 0, c->connect_complete_userdata);
-
- return;
- }
-
- c->pstream = pa_pstream_new(c->mainloop, io);
- assert(c->pstream);
- pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c);
- pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c);
- pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c);
- c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX);
- assert(c->pdispatch);
+ assert(s && length);
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_AUTH);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_put_arbitrary(t, c->auth_cookie, sizeof(c->auth_cookie));
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c);
- c->state = CONTEXT_AUTHORIZING;
-}
-
-static struct sockaddr *resolve_server(const char *server, size_t *len) {
- struct sockaddr *sa;
- struct addrinfo hints, *result = NULL;
- char *port;
- assert(server && len);
-
- if ((port = strrchr(server, ':')))
- port++;
- if (!port)
- port = DEFAULT_PORT;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = 0;
-
- if (getaddrinfo(server, port, &hints, &result) != 0)
- return NULL;
- assert(result);
-
- sa = pa_xmalloc(*len = result->ai_addrlen);
- memcpy(sa, result->ai_addr, *len);
-
- freeaddrinfo(result);
-
- return sa;
-}
-
-int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata) {
- assert(c && c->state == CONTEXT_UNCONNECTED);
-
- if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE, c->auth_cookie, sizeof(c->auth_cookie)) < 0) {
- c->error = PA_ERROR_AUTHKEY;
- return -1;
- }
-
- if (!server)
- if (!(server = getenv("POLYP_SERVER")))
- server = DEFAULT_SERVER;
-
- assert(!c->client);
+ pa_stream_ref(s);
- if (*server == '/') {
- if (!(c->client = pa_socket_client_new_unix(c->mainloop, server))) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- return -1;
- }
- } else {
- struct sockaddr* sa;
- size_t sa_len;
-
- if (!(sa = resolve_server(server, &sa_len))) {
- c->error = PA_ERROR_INVALIDSERVER;
- return -1;
- }
-
- c->client = pa_socket_client_new_sockaddr(c->mainloop, sa, sa_len);
- pa_xfree(sa);
-
- if (!c->client) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- return -1;
- }
- }
-
- c->connect_complete_callback = complete;
- c->connect_complete_userdata = userdata;
-
- pa_socket_client_set_callback(c->client, on_connection, c);
- c->state = CONTEXT_CONNECTING;
-
- return 0;
-}
-
-int pa_context_is_dead(struct pa_context *c) {
- assert(c);
- return c->state == CONTEXT_DEAD;
-}
-
-int pa_context_is_ready(struct pa_context *c) {
- assert(c);
- return c->state == CONTEXT_READY;
-}
-
-int pa_context_errno(struct pa_context *c) {
- assert(c);
- return c->error;
-}
-
-void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata) {
- assert(c);
- c->die_callback = cb;
- c->die_userdata = userdata;
-}
-
-static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_stream *s;
- uint32_t channel;
- assert(pd && (command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED) && t && c);
-
- if (pa_tagstruct_getu32(t, &channel) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel)))
- return;
-
- c->error = PA_ERROR_KILLED;
- stream_dead(s);
-}
-
-static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s;
- struct pa_context *c = userdata;
- uint32_t bytes, channel;
- assert(pd && command == PA_COMMAND_REQUEST && t && c);
-
- if (pa_tagstruct_getu32(t, &channel) < 0 ||
- pa_tagstruct_getu32(t, &bytes) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (!(s = pa_dynarray_get(c->playback_streams, channel)))
- return;
-
- if (s->state != STREAM_READY)
- return;
-
- s->requested_bytes += bytes;
-
- if (s->requested_bytes && s->write_callback)
- s->write_callback(s, s->requested_bytes, s->write_userdata);
-}
-
-static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s && s->state == STREAM_CREATING);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- stream_dead(s);
- if (s->create_complete_callback)
- s->create_complete_callback(s, 0, s->create_complete_userdata);
-
- return;
- }
-
- if (pa_tagstruct_getu32(t, &s->channel) < 0 ||
- ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) ||
- !pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- s->channel_valid = 1;
- pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s);
-
- s->state = STREAM_READY;
- if (s->create_complete_callback)
- s->create_complete_callback(s, 1, s->create_complete_userdata);
-}
-
-static void create_stream(struct pa_stream *s, const char *dev) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(s);
+ s->state = PA_STREAM_CREATING;
+ s->direction = PA_STREAM_UPLOAD;
- s->state = STREAM_CREATING;
-
t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM);
+ pa_tagstruct_putu32(t, PA_COMMAND_CREATE_UPLOAD_STREAM);
pa_tagstruct_putu32(t, tag = s->context->ctag++);
pa_tagstruct_puts(t, s->name);
pa_tagstruct_put_sample_spec(t, &s->sample_spec);
- pa_tagstruct_putu32(t, (uint32_t) -1);
- pa_tagstruct_puts(t, dev ? dev : "");
- pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
- if (s->direction == PA_STREAM_PLAYBACK) {
- pa_tagstruct_putu32(t, s->buffer_attr.tlength);
- pa_tagstruct_putu32(t, s->buffer_attr.prebuf);
- pa_tagstruct_putu32(t, s->buffer_attr.minreq);
- } else
- pa_tagstruct_putu32(t, s->buffer_attr.fragsize);
-
+ pa_tagstruct_putu32(t, length);
pa_pstream_send_tagstruct(s->context->pstream, t);
- pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s);
-}
-
-static struct pa_stream *internal_stream_new(struct pa_context *c) {
- struct pa_stream *s;
-
- s = pa_xmalloc(sizeof(struct pa_stream));
- s->context = c;
-
- s->read_callback = NULL;
- s->read_userdata = NULL;
- s->write_callback = NULL;
- s->write_userdata = NULL;
- s->die_callback = NULL;
- s->die_userdata = NULL;
- s->create_complete_callback = NULL;
- s->create_complete_userdata = NULL;
- s->get_latency_callback = NULL;
- s->get_latency_userdata = NULL;
- s->finish_sample_callback = NULL;
- s->finish_sample_userdata = NULL;
-
- s->name = NULL;
- s->state = STREAM_CREATING;
- s->requested_bytes = 0;
- s->channel = 0;
- s->channel_valid = 0;
- s->device_index = (uint32_t) -1;
-
- memset(&s->buffer_attr, 0, sizeof(s->buffer_attr));
-
- s->next = c->first_stream;
- if (s->next)
- s->next->previous = s;
- s->previous = NULL;
- c->first_stream = s;
-
- return s;
-}
-
-struct pa_stream* pa_stream_new(
- struct pa_context *c,
- enum pa_stream_direction dir,
- const char *dev,
- const char *name,
- const struct pa_sample_spec *ss,
- const struct pa_buffer_attr *attr,
- void (*complete) (struct pa_stream*s, int success, void *userdata),
- void *userdata) {
-
- struct pa_stream *s;
-
- assert(c && name && ss && c->state == CONTEXT_READY && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD));
-
- s = internal_stream_new(c);
- assert(s);
-
- s->create_complete_callback = complete;
- s->create_complete_userdata = userdata;
- s->name = pa_xstrdup(name);
- s->state = STREAM_CREATING;
- s->direction = dir;
- s->sample_spec = *ss;
- if (attr)
- s->buffer_attr = *attr;
- else {
- s->buffer_attr.maxlength = DEFAULT_MAXLENGTH;
- s->buffer_attr.tlength = DEFAULT_TLENGTH;
- s->buffer_attr.prebuf = DEFAULT_PREBUF;
- s->buffer_attr.minreq = DEFAULT_MINREQ;
- s->buffer_attr.fragsize = DEFAULT_FRAGSIZE;
- }
-
- create_stream(s, dev);
-
- return s;
-}
-
-void pa_stream_free(struct pa_stream *s) {
- assert(s && s->context);
-
- if (s->context->pdispatch)
- pa_pdispatch_unregister_reply(s->context->pdispatch, s);
-
- pa_xfree(s->name);
-
- if (s->channel_valid && s->context->state == CONTEXT_READY) {
- struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM :
- (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM));
- pa_tagstruct_putu32(t, s->context->ctag++);
- pa_tagstruct_putu32(t, s->channel);
- pa_pstream_send_tagstruct(s->context->pstream, t);
- }
-
- if (s->channel_valid)
- pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL);
+ pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_create_stream_callback, s);
- if (s->next)
- s->next->previous = s->previous;
- if (s->previous)
- s->previous->next = s->next;
- else
- s->context->first_stream = s->next;
-
- pa_xfree(s);
-}
-
-void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) {
- s->write_callback = cb;
- s->write_userdata = userdata;
-}
-
-void pa_stream_write(struct pa_stream *s, const void *data, size_t length) {
- struct pa_memchunk chunk;
- assert(s && s->context && data && length && s->state == STREAM_READY);
-
- chunk.memblock = pa_memblock_new(length);
- assert(chunk.memblock && chunk.memblock->data);
- memcpy(chunk.memblock->data, data, length);
- chunk.index = 0;
- chunk.length = length;
-
- pa_pstream_send_memblock(s->context->pstream, s->channel, 0, &chunk);
- pa_memblock_unref(chunk.memblock);
-
- /*fprintf(stderr, "Sent %u bytes\n", length);*/
-
- if (length < s->requested_bytes)
- s->requested_bytes -= length;
- else
- s->requested_bytes = 0;
-}
-
-size_t pa_stream_writable_size(struct pa_stream *s) {
- assert(s && s->state == STREAM_READY);
- return s->requested_bytes;
-}
-
-void pa_stream_set_read_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) {
- assert(s && cb);
- s->read_callback = cb;
- s->read_userdata = userdata;
-}
-
-int pa_stream_is_dead(struct pa_stream *s) {
- return s->state == STREAM_DEAD;
-}
-
-int pa_stream_is_ready(struct pa_stream*s) {
- return s->state == STREAM_READY;
-}
-
-void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata) {
- assert(s);
- s->die_callback = cb;
- s->die_userdata = userdata;
-}
-
-int pa_context_is_pending(struct pa_context *c) {
- assert(c);
-
- if (c->state != CONTEXT_READY)
- return 0;
-
- return pa_pstream_is_pending(c->pstream) || pa_pdispatch_is_pending(c->pdispatch);
+ pa_stream_unref(s);
}
-struct pa_context* pa_stream_get_context(struct pa_stream *p) {
- assert(p);
- return p->context;
-}
-
-static void set_dispatch_callbacks(struct pa_context *c);
-
-static void pdispatch_drain_callback(struct pa_pdispatch*pd, void *userdata) {
- set_dispatch_callbacks(userdata);
-}
-
-static void pstream_drain_callback(struct pa_pstream *s, void *userdata) {
- set_dispatch_callbacks(userdata);
-}
-
-static void set_dispatch_callbacks(struct pa_context *c) {
- assert(c && c->state == CONTEXT_READY);
-
- pa_pstream_set_drain_callback(c->pstream, NULL, NULL);
- pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL);
-
- if (pa_pdispatch_is_pending(c->pdispatch)) {
- pa_pdispatch_set_drain_callback(c->pdispatch, pdispatch_drain_callback, c);
- return;
- }
-
- if (pa_pstream_is_pending(c->pstream)) {
- pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c);
- return;
- }
-
- assert(c->drain_complete_callback);
- c->drain_complete_callback(c, c->drain_complete_userdata);
-}
-
-int pa_context_drain(
- struct pa_context *c,
- void (*complete) (struct pa_context*c, void *userdata),
- void *userdata) {
-
- assert(c && c->state == CONTEXT_READY);
-
- if (complete == NULL) {
- c->drain_complete_callback = NULL;
- pa_pstream_set_drain_callback(c->pstream, NULL, NULL);
- pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL);
- return 0;
- }
-
- if (!pa_context_is_pending(c))
- return -1;
-
- c->drain_complete_callback = complete;
- c->drain_complete_userdata = userdata;
-
- set_dispatch_callbacks(c);
-
- return 0;
-}
-
-static void stream_drain_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- stream_dead(s);
- return;
- }
-
- if (s->state != STREAM_READY)
- return;
-
- if (!pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->drain_complete_callback) {
- void (*temp) (struct pa_stream*s, void *userdata) = s->drain_complete_callback;
- s->drain_complete_callback = NULL;
- temp(s, s->drain_complete_userdata);
- }
-}
-
-
-void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata) {
+void pa_stream_finish_upload(struct pa_stream *s) {
struct pa_tagstruct *t;
uint32_t tag;
- assert(s && s->state == STREAM_READY);
+ assert(s);
- if (!complete) {
- s->drain_complete_callback = NULL;
+ if (!s->channel_valid || !s->context->state == PA_CONTEXT_READY)
return;
- }
- s->drain_complete_callback = complete;
- s->drain_complete_userdata = userdata;
+ pa_stream_ref(s);
t = pa_tagstruct_new(NULL, 0);
assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_DRAIN_PLAYBACK_STREAM);
+ pa_tagstruct_putu32(t, PA_COMMAND_FINISH_UPLOAD_STREAM);
pa_tagstruct_putu32(t, tag = s->context->ctag++);
pa_tagstruct_putu32(t, s->channel);
pa_pstream_send_tagstruct(s->context->pstream, t);
- pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_drain_callback, s);
-}
-
-void pa_context_exit(struct pa_context *c) {
- struct pa_tagstruct *t;
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_EXIT);
- pa_tagstruct_putu32(t, c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
-}
-
-static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- uint32_t total, count;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->stat_callback)
- c->stat_callback(c, (uint32_t) -1, (uint32_t) -1, c->stat_userdata);
- return;
- }
-
- if (pa_tagstruct_getu32(t, &count) < 0 ||
- pa_tagstruct_getu32(t, &total) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->stat_callback)
- c->stat_callback(c, count, total, c->stat_userdata);
-}
-
-void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata) {
- uint32_t tag;
- struct pa_tagstruct *t;
-
- c->stat_callback = cb;
- c->stat_userdata = userdata;
-
- if (cb == NULL)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_STAT);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_stat_callback, c);
-}
-
-static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- uint32_t latency;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- if (s->get_latency_callback)
- s->get_latency_callback(s, (uint32_t) -1, s->get_latency_userdata);
- return;
- }
-
- if (pa_tagstruct_getu32(t, &latency) < 0 ||
- !pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->get_latency_callback)
- s->get_latency_callback(s, latency, s->get_latency_userdata);
-}
+ pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_disconnect_callback, s);
-void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata) {
- uint32_t tag;
- struct pa_tagstruct *t;
-
- p->get_latency_callback = cb;
- p->get_latency_userdata = userdata;
-
- if (cb == NULL)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY);
- pa_tagstruct_putu32(t, tag = p->context->ctag++);
- pa_tagstruct_putu32(t, p->channel);
- pa_pstream_send_tagstruct(p->context->pstream, t);
- pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, p);
+ pa_stream_unref(s);
}
-struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) {
- struct pa_stream *s;
- struct pa_tagstruct *t;
- uint32_t tag;
-
- s = internal_stream_new(c);
- assert(s);
-
- s->create_complete_callback = cb;
- s->create_complete_userdata = userdata;
- s->name = pa_xstrdup(name);
- s->state = STREAM_CREATING;
- s->direction = PA_STREAM_UPLOAD;
- s->sample_spec = *ss;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_CREATE_UPLOAD_STREAM);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, name);
- pa_tagstruct_put_sample_spec(t, ss);
- pa_tagstruct_putu32(t, length);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s);
-
- return s;
-}
-
-static void stream_finish_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- if (s->finish_sample_callback)
- s->finish_sample_callback(s, 0, s->finish_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->finish_sample_callback)
- s->finish_sample_callback(s, 1, s->finish_sample_userdata);
-}
-
-void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(p);
-
- p->finish_sample_callback = cb;
- p->finish_sample_userdata = userdata;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_FINISH_UPLOAD_STREAM);
- pa_tagstruct_putu32(t, tag = p->context->ctag++);
- pa_tagstruct_putu32(t, p->channel);
- pa_pstream_send_tagstruct(p->context->pstream, t);
- pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_finish_sample_callback, p);
-}
-
-static void context_play_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->play_sample_callback)
- c->play_sample_callback(c, 0, c->play_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->play_sample_callback)
- c->play_sample_callback(c, 1, c->play_sample_userdata);
-}
-
-void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
+struct pa_operation * pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
+ struct pa_operation *o;
struct pa_tagstruct *t;
uint32_t tag;
assert(c && name && *name && (!dev || *dev));
- c->play_sample_callback = cb;
- c->play_sample_userdata = userdata;
-
- if (!cb)
- return;
+ o = pa_operation_new(c, NULL);
+ o->callback = cb;
+ o->userdata = userdata;
+ if (!dev)
+ dev = getenv(ENV_DEFAULT_SINK);
+
t = pa_tagstruct_new(NULL, 0);
assert(t);
pa_tagstruct_putu32(t, PA_COMMAND_PLAY_SAMPLE);
@@ -1109,44 +99,20 @@ void pa_context_play_sample(struct pa_context *c, const char *name, const char *
pa_tagstruct_putu32(t, volume);
pa_tagstruct_puts(t, name);
pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_play_sample_callback, c);
-}
-
-static void context_remove_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
+ pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o);
- if (c->remove_sample_callback)
- c->remove_sample_callback(c, 0, c->remove_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->remove_sample_callback)
- c->remove_sample_callback(c, 1, c->remove_sample_userdata);
+ return pa_operation_ref(o);
}
-void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
+struct pa_operation* pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
+ struct pa_operation *o;
struct pa_tagstruct *t;
uint32_t tag;
assert(c && name);
- c->remove_sample_callback = cb;
- c->remove_sample_userdata = userdata;
-
- if (!cb)
- return;
+ o = pa_operation_new(c, NULL);
+ o->callback = cb;
+ o->userdata = userdata;
t = pa_tagstruct_new(NULL, 0);
assert(t);
@@ -1154,397 +120,8 @@ void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)
pa_tagstruct_putu32(t, tag = c->ctag++);
pa_tagstruct_puts(t, name);
pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_remove_sample_callback, c);
-}
-
-static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_server_info i;
- assert(pd && c);
+ pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o);
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_server_info_callback)
- c->get_server_info_callback(c, NULL, c->get_server_info_userdata);
- return;
- }
-
- if (pa_tagstruct_gets(t, &i.server_name) < 0 ||
- pa_tagstruct_gets(t, &i.server_version) < 0 ||
- pa_tagstruct_gets(t, &i.user_name) < 0 ||
- pa_tagstruct_gets(t, &i.host_name) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_server_info_callback)
- c->get_server_info_callback(c, &i, c->get_server_info_userdata);
+ return pa_operation_ref(o);
}
-void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_server_info_callback = cb;
- c->get_server_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SERVER_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_server_info_callback, c);
-}
-
-static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, NULL, 0, c->get_sink_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_sink_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.description) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
- pa_tagstruct_getu32(t, &i.volume) < 0 ||
- pa_tagstruct_getu32(t, &i.monitor_source) < 0 ||
- pa_tagstruct_gets(t, &i.monitor_source_name) < 0 ||
- pa_tagstruct_getu32(t, &i.latency) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, &i, 0, c->get_sink_info_userdata);
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, NULL, 1, c->get_sink_info_userdata);
-}
-
-void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_sink_info_callback = cb;
- c->get_sink_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c);
-}
-
-static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, NULL, 0, c->get_source_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_source_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.description) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
- pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 ||
- pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, &i, 0, c->get_source_info_userdata);
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, NULL, 1, c->get_source_info_userdata);
-}
-
-void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_source_info_callback = cb;
- c->get_source_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c);
-}
-
-void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- assert(c);
-
- c->subscribe_callback = cb;
- c->subscribe_userdata = userdata;
- c->subscribe_mask = m;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE);
- pa_tagstruct_putu32(t, c->ctag++);
- pa_tagstruct_putu32(t, cb ? m : 0);
- pa_pstream_send_tagstruct(c->pstream, t);
-}
-
-static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- enum pa_subscription_event_type e;
- uint32_t index;
- assert(pd && command == PA_COMMAND_SUBSCRIBE_EVENT && t && c);
-
- if (pa_tagstruct_getu32(t, &e) < 0 ||
- pa_tagstruct_getu32(t, &index) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (pa_subscription_match_flags(c->subscribe_mask, e) && c->subscribe_callback)
- c->subscribe_callback(c, e, index, c->subscribe_userdata);
-}
-
-void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_sink_info_callback = cb;
- c->get_sink_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_tagstruct_puts(t, "");
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c);
-}
-
-void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_source_info_callback = cb;
- c->get_source_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_tagstruct_puts(t, "");
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c);
-}
-
-static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, NULL, 0, c->get_client_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_client_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.protocol_name) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, &i, 0, c->get_client_info_userdata);
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, NULL, 1, c->get_client_info_userdata);
-}
-
-
-void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_client_info_callback = cb;
- c->get_client_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c);
-}
-
-void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_client_info_callback = cb;
- c->get_client_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c);
-}
-
-static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, NULL, 0, c->get_module_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_module_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.argument) < 0 ||
- pa_tagstruct_getu32(t, &i.n_used) < 0 ||
- pa_tagstruct_getu32(t, &i.auto_unload) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, &i, 0, c->get_module_info_userdata);
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, NULL, 1, c->get_module_info_userdata);
-}
-
-void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_module_info_callback = cb;
- c->get_module_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c);
-}
-
-void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_module_info_callback = cb;
- c->get_module_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c);
-}
diff --git a/polyp/polyplib-scache.h b/polyp/polyplib-scache.h
index a0dd9f9c..ce74bef0 100644
--- a/polyp/polyplib-scache.h
+++ b/polyp/polyplib-scache.h
@@ -1,5 +1,5 @@
-#ifndef foopolyplibhfoo
-#define foopolyplibhfoo
+#ifndef foopolyplibscachehfoo
+#define foopolyplibscachehfoo
/* $Id$ */
@@ -24,155 +24,27 @@
#include <sys/types.h>
-#include "sample.h"
-#include "polyplib-def.h"
-#include "mainloop-api.h"
+#include "polyplib-context.h"
+#include "polyplib-stream.h"
+#include "cdecl.h"
-#ifdef __cplusplus
-//extern "C" {
-#endif
-
-struct pa_context;
-struct pa_stream;
-
-struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name);
-void pa_context_unref(struct pa_context *c);
-struct pa_context* pa_context_ref(struct pa_context *c);
-
-int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata);
-int pa_context_drain(struct pa_context *c, void (*complete) (struct pa_context*c, void *userdata), void *userdata);
-void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata);
-
-int pa_context_is_dead(struct pa_context *c);
-int pa_context_is_ready(struct pa_context *c);
-int pa_context_errno(struct pa_context *c);
-
-int pa_context_is_pending(struct pa_context *c);
-
-struct pa_stream* pa_stream_new(struct pa_context *c, enum pa_stream_direction dir, const char *dev, const char *name, const struct pa_sample_spec *ss, const struct pa_buffer_attr *attr, void (*complete) (struct pa_stream*s, int success, void *userdata), void *userdata);
-void pa_stream_unref(struct pa_stream *s);
-struct pa_stream *pa_stream_ref(struct pa_stream *s);
-
-void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata);
-
-void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata);
-
-void pa_stream_set_write_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata);
-void pa_stream_write(struct pa_stream *p, const void *data, size_t length);
-size_t pa_stream_writable_size(struct pa_stream *p);
-
-void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata);
-
-int pa_stream_is_dead(struct pa_stream *p);
-int pa_stream_is_ready(struct pa_stream*p);
-
-void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata);
-
-struct pa_context* pa_stream_get_context(struct pa_stream *p);
-
-uint32_t pa_stream_get_index(struct pa_stream *s);
+/** \file
+ * All sample cache related routines */
-struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata);
-void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata);
+PA_C_DECL_BEGIN
-void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
+/** Make this stream a sample upload stream */
+void pa_stream_connect_upload(struct pa_stream *s, size_t length);
-struct pa_sink_info {
- const char *name;
- uint32_t index;
- const char *description;
- struct pa_sample_spec sample_spec;
- uint32_t owner_module;
- uint32_t volume;
- uint32_t monitor_source;
- const char *monitor_source_name;
- uint32_t latency;
-};
+/** Finish the sample upload, the stream name will become the sample name. You cancel a sample upload by issuing pa_stream_disconnect() */
+void pa_stream_finish_upload(struct pa_stream *s);
-void pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
+/** Play a sample from the sample cache to the specified device. If the latter is NULL use the default sink. Returns an operation object */
+struct pa_operation* pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-struct pa_source_info {
- const char *name;
- uint32_t index;
- const char *description;
- struct pa_sample_spec sample_spec;
- uint32_t owner_module;
- uint32_t monitor_of_sink;
- const char *monitor_of_sink_name;
-};
+/** Remove a sample from the sample cache. Returns an operation object which may be used to cancel the operation while it is running */
+struct pa_operation* pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-void pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-
-struct pa_server_info {
- const char *user_name;
- const char *host_name;
- const char *server_version;
- const char *server_name;
- struct pa_sample_spec sample_spec;
-};
-
-void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata);
-
-struct pa_module_info {
- uint32_t index;
- const char*name, *argument;
- uint32_t n_used, auto_unload;
-};
-
-void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata);
-
-struct pa_client_info {
- uint32_t index;
- const char *name;
- uint32_t owner_module;
- const char *protocol_name;
-};
-
-void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata);
-
-struct pa_sink_input_info {
- uint32_t index;
- const char *name;
- uint32_t owner_module;
- uint32_t owner_client;
- uint32_t sink;
- struct pa_sample_spec sample_spec;
- uint32_t volume;
- uint32_t latency;
-};
-
-void pa_context_get_sink_input_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_input_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata);
-
-struct pa_source_output_info {
- uint32_t index;
- const char *name;
- uint32_t owner_module;
- uint32_t owner_client;
- uint32_t source;
- struct pa_sample_spec sample_spec;
-};
-
-void pa_context_get_source_output_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_output_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata);
-
-void pa_context_set_sink_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-void pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-
-void pa_context_exit(struct pa_context *c);
-void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata);
-
-void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata);
-
-#ifdef __cplusplus
-}
-#endif
+PA_C_DECL_END
#endif
diff --git a/polyp/polyplib-simple.c b/polyp/polyplib-simple.c
index 1f5ea553..66ee5995 100644
--- a/polyp/polyplib-simple.c
+++ b/polyp/polyplib-simple.c
@@ -49,15 +49,28 @@ struct pa_simple {
static void read_callback(struct pa_stream *s, const void*data, size_t length, void *userdata);
static int check_error(struct pa_simple *p, int *perror) {
+ enum pa_context_state cst;
+ enum pa_stream_state sst;
assert(p);
- if (pa_context_is_dead(p->context) || (p->stream && pa_stream_is_dead(p->stream))) {
- if (perror)
- *perror = pa_context_errno(p->context);
- return -1;
- }
+ if ((cst = pa_context_get_state(p->context)) == PA_CONTEXT_FAILED)
+ goto fail;
+ assert(cst != PA_CONTEXT_TERMINATED);
+
+ if (p->stream) {
+ if ((sst = pa_stream_get_state(p->stream)) == PA_STREAM_FAILED)
+ goto fail;
+
+ assert(sst != PA_STREAM_TERMINATED);
+ }
+
return 0;
+
+fail:
+ if (perror)
+ *perror = pa_context_errno(p->context);
+ return -1;
}
static int iterate(struct pa_simple *p, int block, int *perror) {
@@ -96,7 +109,7 @@ struct pa_simple* pa_simple_new(
struct pa_simple *p;
int error = PA_ERROR_INTERNAL;
- assert(ss);
+ assert(ss && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD));
p = pa_xmalloc(sizeof(struct pa_simple));
p->context = NULL;
@@ -110,23 +123,25 @@ struct pa_simple* pa_simple_new(
if (!(p->context = pa_context_new(pa_mainloop_get_api(p->mainloop), name)))
goto fail;
-
- if (pa_context_connect(p->context, server, NULL, NULL) < 0) {
- error = pa_context_errno(p->context);
- goto fail;
- }
+
+ pa_context_connect(p->context, server);
/* Wait until the context is ready */
- while (!pa_context_is_ready(p->context)) {
+ while (pa_context_get_state(p->context) != PA_CONTEXT_READY) {
if (iterate(p, 1, &error) < 0)
goto fail;
}
- if (!(p->stream = pa_stream_new(p->context, dir, dev, stream_name, ss, attr, NULL, NULL)))
+ if (!(p->stream = pa_stream_new(p->context, stream_name, ss)))
goto fail;
+ if (dir == PA_STREAM_PLAYBACK)
+ pa_stream_connect_playback(p->stream, dev, attr);
+ else
+ pa_stream_connect_record(p->stream, dev, attr);
+
/* Wait until the stream is ready */
- while (!pa_stream_is_ready(p->stream)) {
+ while (pa_stream_get_state(p->stream) != PA_STREAM_READY) {
if (iterate(p, 1, &error) < 0)
goto fail;
}
@@ -148,10 +163,10 @@ void pa_simple_free(struct pa_simple *s) {
pa_xfree(s->read_data);
if (s->stream)
- pa_stream_free(s->stream);
+ pa_stream_unref(s->stream);
if (s->context)
- pa_context_free(s->context);
+ pa_context_unref(s->context);
if (s->mainloop)
pa_mainloop_free(s->mainloop);
@@ -172,7 +187,7 @@ int pa_simple_write(struct pa_simple *p, const void*data, size_t length, int *pe
if (l > length)
l = length;
- pa_stream_write(p->stream, data, l);
+ pa_stream_write(p->stream, data, l, NULL);
data += l;
length -= l;
}
@@ -193,8 +208,7 @@ static void read_callback(struct pa_stream *s, const void*data, size_t length, v
pa_xfree(p->read_data);
}
- p->read_data = pa_xmalloc(p->read_length = length);
- memcpy(p->read_data, data, length);
+ p->read_data = pa_xmemdup(data, p->read_length = length);
p->read_index = 0;
}
@@ -235,23 +249,31 @@ int pa_simple_read(struct pa_simple *p, void*data, size_t length, int *perror) {
return 0;
}
-static void drain_complete(struct pa_stream *s, void *userdata) {
+static void drain_complete(struct pa_stream *s, int success, void *userdata) {
struct pa_simple *p = userdata;
assert(s && p);
- p->drained = 1;
+ p->drained = success ? 1 : -1;
}
int pa_simple_drain(struct pa_simple *p, int *perror) {
+ struct pa_operation *o;
+
assert(p && p->direction == PA_STREAM_PLAYBACK);
p->drained = 0;
- pa_stream_drain(p->stream, drain_complete, p);
+ o = pa_stream_drain(p->stream, drain_complete, p);
while (!p->drained) {
if (iterate(p, 1, perror) < 0) {
- pa_stream_drain(p->stream, NULL, NULL);
+ pa_operation_cancel(o);
+ pa_operation_unref(o);
return -1;
}
}
+ pa_operation_unref(o);
+
+ if (p->drained < 0 && perror)
+ *perror = pa_context_errno(p->context);
+
return 0;
}
diff --git a/polyp/polyplib-simple.h b/polyp/polyplib-simple.h
index 0544410c..ee2e27e3 100644
--- a/polyp/polyplib-simple.h
+++ b/polyp/polyplib-simple.h
@@ -26,24 +26,41 @@
#include "sample.h"
#include "polyplib-def.h"
+#include "cdecl.h"
+/** \file
+ * A simple but limited synchronous playback and recording API. */
+
+PA_C_DECL_BEGIN
+
+/** \struct pa_simple
+ * A simple connection object */
struct pa_simple;
+/** Create a new connection to the server */
struct pa_simple* pa_simple_new(
- const char *server,
- const char *name,
- enum pa_stream_direction dir,
- const char *dev,
- const char *stream_name,
- const struct pa_sample_spec *ss,
- const struct pa_buffer_attr *attr,
- int *error);
+ const char *server, /**< Server name, or NULL for default */
+ const char *name, /**< A descriptive name for this client (application name, ...) */
+ enum pa_stream_direction dir, /**< Open this stream for recording or playback? */
+ const char *dev, /**< Sink (resp. source) name, or NULL for default */
+ const char *stream_name, /**< A descriptive name for this client (application name, song title, ...) */
+ const struct pa_sample_spec *ss, /**< The sample type to use */
+ const struct pa_buffer_attr *attr, /**< Buffering attributes, or NULL for default */
+ int *error /**< A pointer where the error code is stored when the routine returns NULL. It is OK to pass NULL here. */
+ );
+/** Close and free the connection to the server. The connection objects becomes invalid when this is called. */
void pa_simple_free(struct pa_simple *s);
+/** Write some data to the server */
int pa_simple_write(struct pa_simple *s, const void*data, size_t length, int *error);
+
+/** Wait until all data already written is played by the daemon */
int pa_simple_drain(struct pa_simple *s, int *error);
+/** Read some data from the server */
int pa_simple_read(struct pa_simple *s, void*data, size_t length, int *error);
+PA_C_DECL_END
+
#endif
diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c
index 35001d3d..362dbad1 100644
--- a/polyp/polyplib-stream.c
+++ b/polyp/polyplib-stream.c
@@ -23,576 +23,217 @@
#include <config.h>
#endif
-#include <stdio.h>
#include <assert.h>
-#include <stdlib.h>
#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-
-#include "polyplib.h"
-#include "native-common.h"
-#include "pdispatch.h"
-#include "pstream.h"
-#include "dynarray.h"
-#include "socket-client.h"
-#include "pstream-util.h"
-#include "authkey.h"
-#include "util.h"
-#include "xmalloc.h"
-
-#define DEFAULT_MAXLENGTH 204800
-#define DEFAULT_TLENGTH 10240
-#define DEFAULT_PREBUF 4096
-#define DEFAULT_MINREQ 1024
-#define DEFAULT_FRAGSIZE 1024
-
-#define DEFAULT_TIMEOUT (5*60)
-#define DEFAULT_SERVER "/tmp/polypaudio/native"
-#define DEFAULT_PORT "4713"
-
-struct pa_context {
- char *name;
- struct pa_mainloop_api* mainloop;
- struct pa_socket_client *client;
- struct pa_pstream *pstream;
- struct pa_pdispatch *pdispatch;
- struct pa_dynarray *record_streams, *playback_streams;
- struct pa_stream *first_stream;
- uint32_t ctag;
- uint32_t error;
- enum {
- CONTEXT_UNCONNECTED,
- CONTEXT_CONNECTING,
- CONTEXT_AUTHORIZING,
- CONTEXT_SETTING_NAME,
- CONTEXT_READY,
- CONTEXT_DEAD
- } state;
-
- void (*connect_complete_callback)(struct pa_context*c, int success, void *userdata);
- void *connect_complete_userdata;
-
- void (*drain_complete_callback)(struct pa_context*c, void *userdata);
- void *drain_complete_userdata;
-
- void (*die_callback)(struct pa_context*c, void *userdata);
- void *die_userdata;
-
- void (*stat_callback)(struct pa_context*c, uint32_t count, uint32_t total, void *userdata);
- void *stat_userdata;
-
- void (*play_sample_callback)(struct pa_context*c, int success, void *userdata);
- void *play_sample_userdata;
-
- void (*remove_sample_callback)(struct pa_context*c, int success, void *userdata);
- void *remove_sample_userdata;
-
- void (*get_server_info_callback)(struct pa_context*c, const struct pa_server_info* i, void *userdata);
- void *get_server_info_userdata;
-
- void (*get_sink_info_callback)(struct pa_context*c, const struct pa_sink_info* i, int is_last, void *userdata);
- void *get_sink_info_userdata;
-
- void (*get_source_info_callback)(struct pa_context*c, const struct pa_source_info* i, int is_last, void *userdata);
- void *get_source_info_userdata;
-
- void (*subscribe_callback)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata);
- void *subscribe_userdata;
- enum pa_subscription_mask subscribe_mask;
-
- void (*get_client_info_callback)(struct pa_context*c, const struct pa_client_info* i, int is_last, void *userdata);
- void *get_client_info_userdata;
-
- void (*get_module_info_callback)(struct pa_context*c, const struct pa_module_info* i, int is_last, void *userdata);
- void *get_module_info_userdata;
-
- uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH];
-};
-
-struct pa_stream {
- struct pa_context *context;
- struct pa_stream *next, *previous;
-
- char *name;
- struct pa_buffer_attr buffer_attr;
- struct pa_sample_spec sample_spec;
- uint32_t channel;
- int channel_valid;
- uint32_t device_index;
- enum pa_stream_direction direction;
-
- enum { STREAM_CREATING, STREAM_READY, STREAM_DEAD} state;
- uint32_t requested_bytes;
-
- void (*read_callback)(struct pa_stream *p, const void*data, size_t length, void *userdata);
- void *read_userdata;
-
- void (*write_callback)(struct pa_stream *p, size_t length, void *userdata);
- void *write_userdata;
-
- void (*create_complete_callback)(struct pa_stream *s, int success, void *userdata);
- void *create_complete_userdata;
-
- void (*drain_complete_callback)(struct pa_stream *s, void *userdata);
- void *drain_complete_userdata;
-
- void (*die_callback)(struct pa_stream*c, void *userdata);
- void *die_userdata;
-
- void (*get_latency_callback)(struct pa_stream*c, uint32_t latency, void *userdata);
- void *get_latency_userdata;
-
- void (*finish_sample_callback)(struct pa_stream*c, int success, void *userdata);
- void *finish_sample_userdata;
-};
-
-static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-
-static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = {
- [PA_COMMAND_ERROR] = { NULL },
- [PA_COMMAND_REPLY] = { NULL },
- [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { NULL },
- [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { NULL },
- [PA_COMMAND_CREATE_RECORD_STREAM] = { NULL },
- [PA_COMMAND_DELETE_RECORD_STREAM] = { NULL },
- [PA_COMMAND_EXIT] = { NULL },
- [PA_COMMAND_REQUEST] = { command_request },
- [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { command_playback_stream_killed },
- [PA_COMMAND_RECORD_STREAM_KILLED] = { command_playback_stream_killed },
- [PA_COMMAND_SUBSCRIBE_EVENT] = { command_subscribe_event },
-};
-
-struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) {
- struct pa_context *c;
- assert(mainloop && name);
-
- c = pa_xmalloc(sizeof(struct pa_context));
- c->name = pa_xstrdup(name);
- c->mainloop = mainloop;
- c->client = NULL;
- c->pstream = NULL;
- c->pdispatch = NULL;
- c->playback_streams = pa_dynarray_new();
- assert(c->playback_streams);
- c->record_streams = pa_dynarray_new();
- assert(c->record_streams);
- c->first_stream = NULL;
- c->error = PA_ERROR_OK;
- c->state = CONTEXT_UNCONNECTED;
- c->ctag = 0;
-
- c->connect_complete_callback = NULL;
- c->connect_complete_userdata = NULL;
-
- c->drain_complete_callback = NULL;
- c->drain_complete_userdata = NULL;
-
- c->die_callback = NULL;
- c->die_userdata = NULL;
-
- c->stat_callback = NULL;
- c->stat_userdata = NULL;
-
- c->play_sample_callback = NULL;
- c->play_sample_userdata = NULL;
-
- c->remove_sample_callback = NULL;
- c->remove_sample_userdata = NULL;
+#include <stdio.h>
- c->get_server_info_callback = NULL;
- c->get_server_info_userdata = NULL;
+#include "polyplib-internal.h"
+#include "xmalloc.h"
+#include "pstream-util.h"
- c->get_sink_info_callback = NULL;
- c->get_sink_info_userdata = NULL;
+struct pa_stream *pa_stream_new(struct pa_context *c, const char *name, const struct pa_sample_spec *ss) {
+ assert(c && ss);
+ struct pa_stream *s;
- c->get_source_info_callback = NULL;
- c->get_source_info_userdata = NULL;
+ s = pa_xmalloc(sizeof(struct pa_stream));
+ s->ref = 1;
+ s->context = c;
- c->subscribe_callback = NULL;
- c->subscribe_userdata = NULL;
+ s->read_callback = NULL;
+ s->read_userdata = NULL;
+ s->write_callback = NULL;
+ s->write_userdata = NULL;
+ s->state_callback = NULL;
+ s->state_userdata = NULL;
- c->get_client_info_callback = NULL;
- c->get_client_info_userdata = NULL;
-
- c->get_module_info_callback = NULL;
- c->get_module_info_userdata = NULL;
-
- pa_check_for_sigpipe();
- return c;
-}
+ s->state = PA_STREAM_NODIRECTION;
+ s->name = pa_xstrdup(name);
+ s->sample_spec = *ss;
+ s->channel = 0;
+ s->channel_valid = 0;
+ s->device_index = PA_INVALID_INDEX;
+ s->requested_bytes = 0;
+ s->state = PA_STREAM_DISCONNECTED;
+ memset(&s->buffer_attr, 0, sizeof(s->buffer_attr));
-void pa_context_free(struct pa_context *c) {
- assert(c);
+ PA_LLIST_PREPEND(struct pa_stream, c->streams, s);
- while (c->first_stream)
- pa_stream_free(c->first_stream);
-
- if (c->client)
- pa_socket_client_free(c->client);
- if (c->pdispatch)
- pa_pdispatch_free(c->pdispatch);
- if (c->pstream)
- pa_pstream_free(c->pstream);
- if (c->record_streams)
- pa_dynarray_free(c->record_streams, NULL, NULL);
- if (c->playback_streams)
- pa_dynarray_free(c->playback_streams, NULL, NULL);
-
- pa_xfree(c->name);
- pa_xfree(c);
+ return pa_stream_ref(s);
}
-static void stream_dead(struct pa_stream *s) {
+static void stream_free(struct pa_stream *s) {
assert(s);
-
- if (s->state == STREAM_DEAD)
- return;
-
- if (s->state == STREAM_READY) {
- s->state = STREAM_DEAD;
- if (s->die_callback)
- s->die_callback(s, s->die_userdata);
- } else
- s->state = STREAM_DEAD;
-}
-
-static void context_dead(struct pa_context *c) {
- struct pa_stream *s;
- assert(c);
-
- if (c->state == CONTEXT_DEAD)
- return;
-
- if (c->pdispatch)
- pa_pdispatch_free(c->pdispatch);
- c->pdispatch = NULL;
-
- if (c->pstream)
- pa_pstream_free(c->pstream);
- c->pstream = NULL;
-
- if (c->client)
- pa_socket_client_free(c->client);
- c->client = NULL;
-
- for (s = c->first_stream; s; s = s->next)
- stream_dead(s);
-
- if (c->state == CONTEXT_READY) {
- c->state = CONTEXT_DEAD;
- if (c->die_callback)
- c->die_callback(c, c->die_userdata);
- } else
- c->state = CONTEXT_DEAD;
-}
-
-static void pstream_die_callback(struct pa_pstream *p, void *userdata) {
- struct pa_context *c = userdata;
- assert(p && c);
- c->error = PA_ERROR_CONNECTIONTERMINATED;
- context_dead(c);
+ pa_xfree(s->name);
+ pa_xfree(s);
}
-static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) {
- struct pa_context *c = userdata;
- assert(p && packet && c);
+void pa_stream_unref(struct pa_stream *s) {
+ assert(s && s->ref >= 1);
- if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) {
- fprintf(stderr, "polyp.c: invalid packet.\n");
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- }
+ if (--(s->ref) == 0)
+ stream_free(s);
}
-static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_stream *s;
- assert(p && chunk && c && chunk->memblock && chunk->memblock->data);
-
- if (!(s = pa_dynarray_get(c->record_streams, channel)))
- return;
-
- if (s->read_callback)
- s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata);
+struct pa_stream* pa_stream_ref(struct pa_stream *s) {
+ assert(s && s->ref >= 1);
+ s->ref++;
+ return s;
}
-static int handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t) {
- assert(c && t);
-
- if (command == PA_COMMAND_ERROR) {
- if (pa_tagstruct_getu32(t, &c->error) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- return -1;
- }
-
- return 0;
- }
-
- c->error = (command == PA_COMMAND_TIMEOUT) ? PA_ERROR_TIMEOUT : PA_ERROR_INTERNAL;
- return -1;
+enum pa_stream_state pa_stream_get_state(struct pa_stream *s) {
+ assert(s && s->ref >= 1);
+ return s->state;
}
-static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c && (c->state == CONTEXT_AUTHORIZING || c->state == CONTEXT_SETTING_NAME));
-
- if (command != PA_COMMAND_REPLY) {
- handle_error(c, command, t);
- context_dead(c);
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 0, c->connect_complete_userdata);
-
- return;
- }
-
- if (c->state == CONTEXT_AUTHORIZING) {
- struct pa_tagstruct *t;
- c->state = CONTEXT_SETTING_NAME;
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_SET_NAME);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, c->name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c);
- } else {
- assert(c->state == CONTEXT_SETTING_NAME);
-
- c->state = CONTEXT_READY;
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 1, c->connect_complete_userdata);
- }
-
- return;
+struct pa_context* pa_stream_get_context(struct pa_stream *s) {
+ assert(s && s->ref >= 1);
+ return s->context;
}
-static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(client && c && c->state == CONTEXT_CONNECTING);
-
- pa_socket_client_free(client);
- c->client = NULL;
-
- if (!io) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- context_dead(c);
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 0, c->connect_complete_userdata);
-
- return;
- }
-
- c->pstream = pa_pstream_new(c->mainloop, io);
- assert(c->pstream);
- pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c);
- pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c);
- pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c);
-
- c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX);
- assert(c->pdispatch);
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_AUTH);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_put_arbitrary(t, c->auth_cookie, sizeof(c->auth_cookie));
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c);
- c->state = CONTEXT_AUTHORIZING;
+uint32_t pa_stream_get_index(struct pa_stream *s) {
+ assert(s && s->ref >= 1);
+ return s->device_index;
}
-
-static struct sockaddr *resolve_server(const char *server, size_t *len) {
- struct sockaddr *sa;
- struct addrinfo hints, *result = NULL;
- char *port;
- assert(server && len);
-
- if ((port = strrchr(server, ':')))
- port++;
- if (!port)
- port = DEFAULT_PORT;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = 0;
-
- if (getaddrinfo(server, port, &hints, &result) != 0)
- return NULL;
- assert(result);
- sa = pa_xmalloc(*len = result->ai_addrlen);
- memcpy(sa, result->ai_addr, *len);
+void pa_stream_set_state(struct pa_stream *s, enum pa_stream_state st) {
+ assert(s && s->ref >= 1);
- freeaddrinfo(result);
+ if (s->state == st)
+ return;
- return sa;
-}
-
-int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata) {
- assert(c && c->state == CONTEXT_UNCONNECTED);
+ pa_stream_ref(s);
- if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE, c->auth_cookie, sizeof(c->auth_cookie)) < 0) {
- c->error = PA_ERROR_AUTHKEY;
- return -1;
- }
-
- if (!server)
- if (!(server = getenv("POLYP_SERVER")))
- server = DEFAULT_SERVER;
-
- assert(!c->client);
+ s->state = st;
- if (*server == '/') {
- if (!(c->client = pa_socket_client_new_unix(c->mainloop, server))) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- return -1;
- }
- } else {
- struct sockaddr* sa;
- size_t sa_len;
+ if ((st == PA_STREAM_FAILED || st == PA_STREAM_TERMINATED) && s->context) {
+ if (s->channel_valid)
+ pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL);
- if (!(sa = resolve_server(server, &sa_len))) {
- c->error = PA_ERROR_INVALIDSERVER;
- return -1;
- }
-
- c->client = pa_socket_client_new_sockaddr(c->mainloop, sa, sa_len);
- pa_xfree(sa);
-
- if (!c->client) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- return -1;
- }
+ PA_LLIST_REMOVE(struct pa_stream, s->context->streams, s);
+ pa_stream_unref(s);
}
- c->connect_complete_callback = complete;
- c->connect_complete_userdata = userdata;
-
- pa_socket_client_set_callback(c->client, on_connection, c);
- c->state = CONTEXT_CONNECTING;
-
- return 0;
-}
-
-int pa_context_is_dead(struct pa_context *c) {
- assert(c);
- return c->state == CONTEXT_DEAD;
-}
-
-int pa_context_is_ready(struct pa_context *c) {
- assert(c);
- return c->state == CONTEXT_READY;
-}
-
-int pa_context_errno(struct pa_context *c) {
- assert(c);
- return c->error;
-}
+ if (s->state_callback)
+ s->state_callback(s, s->state_userdata);
-void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata) {
- assert(c);
- c->die_callback = cb;
- c->die_userdata = userdata;
+ pa_stream_unref(s);
}
-static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
+void pa_command_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
struct pa_context *c = userdata;
struct pa_stream *s;
uint32_t channel;
assert(pd && (command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED) && t && c);
+ pa_context_ref(c);
+
if (pa_tagstruct_getu32(t, &channel) < 0 ||
!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
+ pa_context_fail(c, PA_ERROR_PROTOCOL);
+ goto finish;
}
if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel)))
- return;
+ goto finish;
c->error = PA_ERROR_KILLED;
- stream_dead(s);
+ pa_stream_set_state(s, PA_STREAM_FAILED);
+
+finish:
+ pa_context_unref(c);
}
-static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
+void pa_command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
struct pa_stream *s;
struct pa_context *c = userdata;
uint32_t bytes, channel;
assert(pd && command == PA_COMMAND_REQUEST && t && c);
+ pa_context_ref(c);
+
if (pa_tagstruct_getu32(t, &channel) < 0 ||
pa_tagstruct_getu32(t, &bytes) < 0 ||
!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
+ pa_context_fail(c, PA_ERROR_PROTOCOL);
+ goto finish;
}
if (!(s = pa_dynarray_get(c->playback_streams, channel)))
- return;
+ goto finish;
- if (s->state != STREAM_READY)
- return;
+ if (s->state != PA_STREAM_READY)
+ goto finish;
+
+ pa_stream_ref(s);
s->requested_bytes += bytes;
if (s->requested_bytes && s->write_callback)
s->write_callback(s, s->requested_bytes, s->write_userdata);
+
+ pa_stream_unref(s);
+
+finish:
+ pa_context_unref(c);
}
-static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
+void pa_create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
struct pa_stream *s = userdata;
- assert(pd && s && s->state == STREAM_CREATING);
+ assert(pd && s && s->state == PA_STREAM_CREATING);
+ pa_stream_ref(s);
+
if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- stream_dead(s);
- if (s->create_complete_callback)
- s->create_complete_callback(s, 0, s->create_complete_userdata);
-
- return;
+ if (pa_context_handle_error(s->context, command, t) < 0)
+ goto finish;
+
+ pa_stream_set_state(s, PA_STREAM_FAILED);
+ goto finish;
}
if (pa_tagstruct_getu32(t, &s->channel) < 0 ||
((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) ||
!pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
+ pa_context_fail(s->context, PA_ERROR_PROTOCOL);
+ goto finish;
}
s->channel_valid = 1;
pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s);
-
- s->state = STREAM_READY;
- if (s->create_complete_callback)
- s->create_complete_callback(s, 1, s->create_complete_userdata);
+ pa_stream_set_state(s, PA_STREAM_READY);
+
+finish:
+ pa_stream_unref(s);
}
-static void create_stream(struct pa_stream *s, const char *dev) {
+static void create_stream(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr) {
struct pa_tagstruct *t;
uint32_t tag;
- assert(s);
+ assert(s && s->ref >= 1 && s->state == PA_STREAM_DISCONNECTED);
+
+ pa_stream_ref(s);
+
+ if (attr)
+ s->buffer_attr = *attr;
+ else {
+ s->buffer_attr.maxlength = DEFAULT_MAXLENGTH;
+ s->buffer_attr.tlength = DEFAULT_TLENGTH;
+ s->buffer_attr.prebuf = DEFAULT_PREBUF;
+ s->buffer_attr.minreq = DEFAULT_MINREQ;
+ s->buffer_attr.fragsize = DEFAULT_FRAGSIZE;
+ }
- s->state = STREAM_CREATING;
+ pa_stream_set_state(s, PA_STREAM_CREATING);
t = pa_tagstruct_new(NULL, 0);
assert(t);
+
+ if (!dev) {
+ if (s->direction == PA_STREAM_PLAYBACK)
+ dev = getenv(ENV_DEFAULT_SINK);
+ else
+ dev = getenv(ENV_DEFAULT_SOURCE);
+ }
pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM);
pa_tagstruct_putu32(t, tag = s->context->ctag++);
@@ -609,135 +250,40 @@ static void create_stream(struct pa_stream *s, const char *dev) {
pa_tagstruct_putu32(t, s->buffer_attr.fragsize);
pa_pstream_send_tagstruct(s->context->pstream, t);
- pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s);
-}
-
-static struct pa_stream *internal_stream_new(struct pa_context *c) {
- struct pa_stream *s;
-
- s = pa_xmalloc(sizeof(struct pa_stream));
- s->context = c;
+ pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_create_stream_callback, s);
- s->read_callback = NULL;
- s->read_userdata = NULL;
- s->write_callback = NULL;
- s->write_userdata = NULL;
- s->die_callback = NULL;
- s->die_userdata = NULL;
- s->create_complete_callback = NULL;
- s->create_complete_userdata = NULL;
- s->get_latency_callback = NULL;
- s->get_latency_userdata = NULL;
- s->finish_sample_callback = NULL;
- s->finish_sample_userdata = NULL;
-
- s->name = NULL;
- s->state = STREAM_CREATING;
- s->requested_bytes = 0;
- s->channel = 0;
- s->channel_valid = 0;
- s->device_index = (uint32_t) -1;
-
- memset(&s->buffer_attr, 0, sizeof(s->buffer_attr));
-
- s->next = c->first_stream;
- if (s->next)
- s->next->previous = s;
- s->previous = NULL;
- c->first_stream = s;
-
- return s;
-}
-
-struct pa_stream* pa_stream_new(
- struct pa_context *c,
- enum pa_stream_direction dir,
- const char *dev,
- const char *name,
- const struct pa_sample_spec *ss,
- const struct pa_buffer_attr *attr,
- void (*complete) (struct pa_stream*s, int success, void *userdata),
- void *userdata) {
-
- struct pa_stream *s;
-
- assert(c && name && ss && c->state == CONTEXT_READY && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD));
-
- s = internal_stream_new(c);
- assert(s);
-
- s->create_complete_callback = complete;
- s->create_complete_userdata = userdata;
- s->name = pa_xstrdup(name);
- s->state = STREAM_CREATING;
- s->direction = dir;
- s->sample_spec = *ss;
- if (attr)
- s->buffer_attr = *attr;
- else {
- s->buffer_attr.maxlength = DEFAULT_MAXLENGTH;
- s->buffer_attr.tlength = DEFAULT_TLENGTH;
- s->buffer_attr.prebuf = DEFAULT_PREBUF;
- s->buffer_attr.minreq = DEFAULT_MINREQ;
- s->buffer_attr.fragsize = DEFAULT_FRAGSIZE;
- }
-
- create_stream(s, dev);
-
- return s;
+ pa_stream_unref(s);
}
-void pa_stream_free(struct pa_stream *s) {
- assert(s && s->context);
-
- if (s->context->pdispatch)
- pa_pdispatch_unregister_reply(s->context->pdispatch, s);
-
- pa_xfree(s->name);
-
- if (s->channel_valid && s->context->state == CONTEXT_READY) {
- struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM :
- (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM));
- pa_tagstruct_putu32(t, s->context->ctag++);
- pa_tagstruct_putu32(t, s->channel);
- pa_pstream_send_tagstruct(s->context->pstream, t);
- }
-
- if (s->channel_valid)
- pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL);
-
- if (s->next)
- s->next->previous = s->previous;
- if (s->previous)
- s->previous->next = s->next;
- else
- s->context->first_stream = s->next;
-
- pa_xfree(s);
+void pa_stream_connect_playback(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr) {
+ assert(s && s->context->state == PA_CONTEXT_READY && s->ref >= 1);
+ s->direction = PA_STREAM_PLAYBACK;
+ create_stream(s, dev, attr);
}
-void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) {
- s->write_callback = cb;
- s->write_userdata = userdata;
+void pa_stream_connect_record(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr) {
+ assert(s && s->context->state == PA_CONTEXT_READY && s->ref >= 1);
+ s->direction = PA_STREAM_RECORD;
+ create_stream(s, dev, attr);
}
-void pa_stream_write(struct pa_stream *s, const void *data, size_t length) {
+void pa_stream_write(struct pa_stream *s, const void *data, size_t length, void (*free_cb)(void *p)) {
struct pa_memchunk chunk;
- assert(s && s->context && data && length && s->state == STREAM_READY);
+ assert(s && s->context && data && length && s->state == PA_STREAM_READY && s->ref >= 1);
- chunk.memblock = pa_memblock_new(length);
- assert(chunk.memblock && chunk.memblock->data);
- memcpy(chunk.memblock->data, data, length);
+ if (free_cb) {
+ chunk.memblock = pa_memblock_new_user((void*) data, length, free_cb);
+ assert(chunk.memblock && chunk.memblock->data);
+ } else {
+ chunk.memblock = pa_memblock_new(length);
+ assert(chunk.memblock && chunk.memblock->data);
+ memcpy(chunk.memblock->data, data, length);
+ }
chunk.index = 0;
chunk.length = length;
pa_pstream_send_memblock(s->context->pstream, s->channel, 0, &chunk);
pa_memblock_unref(chunk.memblock);
-
- /*fprintf(stderr, "Sent %u bytes\n", length);*/
if (length < s->requested_bytes)
s->requested_bytes -= length;
@@ -746,805 +292,163 @@ void pa_stream_write(struct pa_stream *s, const void *data, size_t length) {
}
size_t pa_stream_writable_size(struct pa_stream *s) {
- assert(s && s->state == STREAM_READY);
+ assert(s && s->state == PA_STREAM_READY && s->ref >= 1);
return s->requested_bytes;
}
-void pa_stream_set_read_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) {
- assert(s && cb);
- s->read_callback = cb;
- s->read_userdata = userdata;
-}
-
-int pa_stream_is_dead(struct pa_stream *s) {
- return s->state == STREAM_DEAD;
-}
-
-int pa_stream_is_ready(struct pa_stream*s) {
- return s->state == STREAM_READY;
-}
-
-void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata) {
- assert(s);
- s->die_callback = cb;
- s->die_userdata = userdata;
-}
-
-int pa_context_is_pending(struct pa_context *c) {
- assert(c);
-
- if (c->state != CONTEXT_READY)
- return 0;
-
- return pa_pstream_is_pending(c->pstream) || pa_pdispatch_is_pending(c->pdispatch);
-}
-
-struct pa_context* pa_stream_get_context(struct pa_stream *p) {
- assert(p);
- return p->context;
-}
-
-static void set_dispatch_callbacks(struct pa_context *c);
-
-static void pdispatch_drain_callback(struct pa_pdispatch*pd, void *userdata) {
- set_dispatch_callbacks(userdata);
-}
-
-static void pstream_drain_callback(struct pa_pstream *s, void *userdata) {
- set_dispatch_callbacks(userdata);
-}
-
-static void set_dispatch_callbacks(struct pa_context *c) {
- assert(c && c->state == CONTEXT_READY);
-
- pa_pstream_set_drain_callback(c->pstream, NULL, NULL);
- pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL);
-
- if (pa_pdispatch_is_pending(c->pdispatch)) {
- pa_pdispatch_set_drain_callback(c->pdispatch, pdispatch_drain_callback, c);
- return;
- }
-
- if (pa_pstream_is_pending(c->pstream)) {
- pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c);
- return;
- }
-
- assert(c->drain_complete_callback);
- c->drain_complete_callback(c, c->drain_complete_userdata);
-}
-
-int pa_context_drain(
- struct pa_context *c,
- void (*complete) (struct pa_context*c, void *userdata),
- void *userdata) {
-
- assert(c && c->state == CONTEXT_READY);
-
- if (complete == NULL) {
- c->drain_complete_callback = NULL;
- pa_pstream_set_drain_callback(c->pstream, NULL, NULL);
- pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL);
- return 0;
- }
-
- if (!pa_context_is_pending(c))
- return -1;
-
- c->drain_complete_callback = complete;
- c->drain_complete_userdata = userdata;
-
- set_dispatch_callbacks(c);
-
- return 0;
-}
-
-static void stream_drain_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- stream_dead(s);
- return;
- }
-
- if (s->state != STREAM_READY)
- return;
-
- if (!pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->drain_complete_callback) {
- void (*temp) (struct pa_stream*s, void *userdata) = s->drain_complete_callback;
- s->drain_complete_callback = NULL;
- temp(s, s->drain_complete_userdata);
- }
-}
-
-
-void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata) {
+struct pa_operation * pa_stream_drain(struct pa_stream *s, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) {
+ struct pa_operation *o;
struct pa_tagstruct *t;
uint32_t tag;
- assert(s && s->state == STREAM_READY);
+ assert(s && s->ref >= 1 && s->state == PA_STREAM_READY);
- if (!complete) {
- s->drain_complete_callback = NULL;
- return;
- }
-
- s->drain_complete_callback = complete;
- s->drain_complete_userdata = userdata;
+ o = pa_operation_new(s->context, s);
+ assert(o);
+ o->callback = cb;
+ o->userdata = userdata;
t = pa_tagstruct_new(NULL, 0);
assert(t);
-
pa_tagstruct_putu32(t, PA_COMMAND_DRAIN_PLAYBACK_STREAM);
pa_tagstruct_putu32(t, tag = s->context->ctag++);
pa_tagstruct_putu32(t, s->channel);
pa_pstream_send_tagstruct(s->context->pstream, t);
- pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_drain_callback, s);
-}
-
-void pa_context_exit(struct pa_context *c) {
- struct pa_tagstruct *t;
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_EXIT);
- pa_tagstruct_putu32(t, c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
-}
-
-static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- uint32_t total, count;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->stat_callback)
- c->stat_callback(c, (uint32_t) -1, (uint32_t) -1, c->stat_userdata);
- return;
- }
-
- if (pa_tagstruct_getu32(t, &count) < 0 ||
- pa_tagstruct_getu32(t, &total) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->stat_callback)
- c->stat_callback(c, count, total, c->stat_userdata);
-}
-
-void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata) {
- uint32_t tag;
- struct pa_tagstruct *t;
-
- c->stat_callback = cb;
- c->stat_userdata = userdata;
+ pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_simple_ack_callback, o);
- if (cb == NULL)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_STAT);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_stat_callback, c);
+ return pa_operation_ref(o);
}
static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
+ struct pa_operation *o = userdata;
uint32_t latency;
- assert(pd && s);
+ assert(pd && o && o->stream && o->context);
if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
+ if (pa_context_handle_error(o->context, command, t) < 0)
+ goto finish;
- if (s->get_latency_callback)
- s->get_latency_callback(s, (uint32_t) -1, s->get_latency_userdata);
- return;
+ latency = (uint32_t) -1;
+ } else if (pa_tagstruct_getu32(t, &latency) < 0 || !pa_tagstruct_eof(t)) {
+ pa_context_fail(o->context, PA_ERROR_PROTOCOL);
+ goto finish;
}
- if (pa_tagstruct_getu32(t, &latency) < 0 ||
- !pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
+ if (o->callback) {
+ void (*cb)(struct pa_stream *s, uint32_t latency, void *userdata) = o->callback;
+ cb(o->stream, latency, o->userdata);
}
- if (s->get_latency_callback)
- s->get_latency_callback(s, latency, s->get_latency_userdata);
+finish:
+ pa_operation_done(o);
+ pa_operation_unref(o);
}
-void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata) {
+struct pa_operation* pa_stream_get_latency(struct pa_stream *s, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata) {
uint32_t tag;
+ struct pa_operation *o;
struct pa_tagstruct *t;
- p->get_latency_callback = cb;
- p->get_latency_userdata = userdata;
+ o = pa_operation_new(s->context, s);
+ assert(o);
+ o->callback = cb;
+ o->userdata = userdata;
- if (cb == NULL)
- return;
-
t = pa_tagstruct_new(NULL, 0);
assert(t);
pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY);
- pa_tagstruct_putu32(t, tag = p->context->ctag++);
- pa_tagstruct_putu32(t, p->channel);
- pa_pstream_send_tagstruct(p->context->pstream, t);
- pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, p);
-}
-
-struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) {
- struct pa_stream *s;
- struct pa_tagstruct *t;
- uint32_t tag;
-
- s = internal_stream_new(c);
- assert(s);
-
- s->create_complete_callback = cb;
- s->create_complete_userdata = userdata;
- s->name = pa_xstrdup(name);
- s->state = STREAM_CREATING;
- s->direction = PA_STREAM_UPLOAD;
- s->sample_spec = *ss;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_CREATE_UPLOAD_STREAM);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, name);
- pa_tagstruct_put_sample_spec(t, ss);
- pa_tagstruct_putu32(t, length);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s);
+ pa_tagstruct_putu32(t, tag = s->context->ctag++);
+ pa_tagstruct_putu32(t, s->channel);
+ pa_pstream_send_tagstruct(s->context->pstream, t);
+ pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, o);
- return s;
+ return pa_operation_ref(o);
}
-static void stream_finish_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
+void pa_stream_disconnect_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
struct pa_stream *s = userdata;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
+ assert(pd && s && s->ref >= 1);
- if (s->finish_sample_callback)
- s->finish_sample_callback(s, 0, s->finish_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->finish_sample_callback)
- s->finish_sample_callback(s, 1, s->finish_sample_userdata);
-}
-
-void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(p);
-
- p->finish_sample_callback = cb;
- p->finish_sample_userdata = userdata;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_FINISH_UPLOAD_STREAM);
- pa_tagstruct_putu32(t, tag = p->context->ctag++);
- pa_tagstruct_putu32(t, p->channel);
- pa_pstream_send_tagstruct(p->context->pstream, t);
- pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_finish_sample_callback, p);
-}
-
-static void context_play_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
+ pa_stream_ref(s);
if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
+ if (pa_context_handle_error(s->context, command, t) < 0)
+ goto finish;
- if (c->play_sample_callback)
- c->play_sample_callback(c, 0, c->play_sample_userdata);
- return;
+ pa_stream_set_state(s, PA_STREAM_FAILED);
+ goto finish;
+ } else if (!pa_tagstruct_eof(t)) {
+ pa_context_fail(s->context, PA_ERROR_PROTOCOL);
+ goto finish;
}
- if (!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
+ pa_stream_set_state(s, PA_STREAM_TERMINATED);
- if (c->play_sample_callback)
- c->play_sample_callback(c, 1, c->play_sample_userdata);
+finish:
+ pa_stream_unref(s);
}
-void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
+void pa_stream_disconnect(struct pa_stream *s) {
struct pa_tagstruct *t;
uint32_t tag;
- assert(c && name && *name && (!dev || *dev));
-
- c->play_sample_callback = cb;
- c->play_sample_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_PLAY_SAMPLE);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, (uint32_t) -1);
- pa_tagstruct_puts(t, dev ? dev : "");
- pa_tagstruct_putu32(t, volume);
- pa_tagstruct_puts(t, name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_play_sample_callback, c);
-}
-
-static void context_remove_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->remove_sample_callback)
- c->remove_sample_callback(c, 0, c->remove_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->remove_sample_callback)
- c->remove_sample_callback(c, 1, c->remove_sample_userdata);
-}
-
-void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c && name);
-
- c->remove_sample_callback = cb;
- c->remove_sample_userdata = userdata;
+ assert(s && s->ref >= 1);
- if (!cb)
+ if (!s->channel_valid || !s->context->state == PA_CONTEXT_READY)
return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_SAMPLE);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_remove_sample_callback, c);
-}
-
-static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_server_info i;
- assert(pd && c);
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
+ pa_stream_ref(s);
- if (c->get_server_info_callback)
- c->get_server_info_callback(c, NULL, c->get_server_info_userdata);
- return;
- }
-
- if (pa_tagstruct_gets(t, &i.server_name) < 0 ||
- pa_tagstruct_gets(t, &i.server_version) < 0 ||
- pa_tagstruct_gets(t, &i.user_name) < 0 ||
- pa_tagstruct_gets(t, &i.host_name) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_server_info_callback)
- c->get_server_info_callback(c, &i, c->get_server_info_userdata);
-}
-
-void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_server_info_callback = cb;
- c->get_server_info_userdata = userdata;
-
- if (!cb)
- return;
-
t = pa_tagstruct_new(NULL, 0);
assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SERVER_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_server_info_callback, c);
-}
-
-static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, NULL, 0, c->get_sink_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_sink_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.description) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
- pa_tagstruct_getu32(t, &i.volume) < 0 ||
- pa_tagstruct_getu32(t, &i.monitor_source) < 0 ||
- pa_tagstruct_gets(t, &i.monitor_source_name) < 0 ||
- pa_tagstruct_getu32(t, &i.latency) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, &i, 0, c->get_sink_info_userdata);
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, NULL, 1, c->get_sink_info_userdata);
-}
-
-void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_sink_info_callback = cb;
- c->get_sink_info_userdata = userdata;
-
- if (!cb)
- return;
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c);
-}
-
-static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, NULL, 0, c->get_source_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_source_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.description) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
- pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 ||
- pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, &i, 0, c->get_source_info_userdata);
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, NULL, 1, c->get_source_info_userdata);
-}
-
-void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_source_info_callback = cb;
- c->get_source_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c);
-}
-
-void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- assert(c);
-
- c->subscribe_callback = cb;
- c->subscribe_userdata = userdata;
- c->subscribe_mask = m;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE);
- pa_tagstruct_putu32(t, c->ctag++);
- pa_tagstruct_putu32(t, cb ? m : 0);
- pa_pstream_send_tagstruct(c->pstream, t);
-}
-
-static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- enum pa_subscription_event_type e;
- uint32_t index;
- assert(pd && command == PA_COMMAND_SUBSCRIBE_EVENT && t && c);
-
- if (pa_tagstruct_getu32(t, &e) < 0 ||
- pa_tagstruct_getu32(t, &index) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (pa_subscription_match_flags(c->subscribe_mask, e) && c->subscribe_callback)
- c->subscribe_callback(c, e, index, c->subscribe_userdata);
-}
-
-void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_sink_info_callback = cb;
- c->get_sink_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_tagstruct_puts(t, "");
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c);
-}
-
-void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_source_info_callback = cb;
- c->get_source_info_userdata = userdata;
+ pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM :
+ (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM));
+ pa_tagstruct_putu32(t, tag = s->context->ctag++);
+ pa_tagstruct_putu32(t, s->channel);
+ pa_pstream_send_tagstruct(s->context->pstream, t);
+ pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_stream_disconnect_callback, s);
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_tagstruct_puts(t, "");
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c);
+ pa_stream_unref(s);
}
-static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, NULL, 0, c->get_client_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_client_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.protocol_name) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, &i, 0, c->get_client_info_userdata);
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, NULL, 1, c->get_client_info_userdata);
+void pa_stream_set_read_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) {
+ assert(s && s->ref >= 1);
+ s->read_callback = cb;
+ s->read_userdata = userdata;
}
-
-void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_client_info_callback = cb;
- c->get_client_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c);
+void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) {
+ assert(s && s->ref >= 1);
+ s->write_callback = cb;
+ s->write_userdata = userdata;
}
-void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_client_info_callback = cb;
- c->get_client_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c);
+void pa_stream_set_state_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata) {
+ assert(s && s->ref >= 1);
+ s->state_callback = cb;
+ s->state_userdata = userdata;
}
-static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
+void pa_stream_simple_ack_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
+ struct pa_operation *o = userdata;
+ int success = 1;
+ assert(pd && o && o->context && o->ref >= 1);
if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
+ if (pa_context_handle_error(o->context, command, t) < 0)
+ goto finish;
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, NULL, 0, c->get_module_info_userdata);
- return;
+ success = 0;
+ } else if (!pa_tagstruct_eof(t)) {
+ pa_context_fail(o->context, PA_ERROR_PROTOCOL);
+ goto finish;
}
- while (!pa_tagstruct_eof(t)) {
- struct pa_module_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.argument) < 0 ||
- pa_tagstruct_getu32(t, &i.n_used) < 0 ||
- pa_tagstruct_getu32(t, &i.auto_unload) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, &i, 0, c->get_module_info_userdata);
+ if (o->callback) {
+ void (*cb)(struct pa_stream *s, int success, void *userdata) = o->callback;
+ cb(o->stream, success, o->userdata);
}
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, NULL, 1, c->get_module_info_userdata);
-}
-
-void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_module_info_callback = cb;
- c->get_module_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c);
-}
-
-void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_module_info_callback = cb;
- c->get_module_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c);
+finish:
+ pa_operation_done(o);
+ pa_operation_unref(o);
}
diff --git a/polyp/polyplib-stream.h b/polyp/polyplib-stream.h
index a0dd9f9c..41801c6c 100644
--- a/polyp/polyplib-stream.h
+++ b/polyp/polyplib-stream.h
@@ -1,5 +1,5 @@
-#ifndef foopolyplibhfoo
-#define foopolyplibhfoo
+#ifndef foopolyplibstreamhfoo
+#define foopolyplibstreamhfoo
/* $Id$ */
@@ -26,153 +26,79 @@
#include "sample.h"
#include "polyplib-def.h"
-#include "mainloop-api.h"
+#include "cdecl.h"
+#include "polyplib-operation.h"
-#ifdef __cplusplus
-//extern "C" {
-#endif
-
-struct pa_context;
-struct pa_stream;
+/** \file
+ * Audio streams for input, output and sample upload */
-struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name);
-void pa_context_unref(struct pa_context *c);
-struct pa_context* pa_context_ref(struct pa_context *c);
+PA_C_DECL_BEGIN
-int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata);
-int pa_context_drain(struct pa_context *c, void (*complete) (struct pa_context*c, void *userdata), void *userdata);
-void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata);
+/** The state of a stream */
+enum pa_stream_state {
+ PA_STREAM_DISCONNECTED, /**< The stream is not yet connected to any sink or source */
+ PA_STREAM_CREATING, /**< The stream is being created */
+ PA_STREAM_READY, /**< The stream is established, you may pass audio data to it now */
+ PA_STREAM_FAILED, /**< An error occured that made the stream invalid */
+ PA_STREAM_TERMINATED, /**< The stream has been terminated cleanly */
+};
-int pa_context_is_dead(struct pa_context *c);
-int pa_context_is_ready(struct pa_context *c);
-int pa_context_errno(struct pa_context *c);
+/** \struct pa_stream
+ * A stream for playback or recording */
+struct pa_stream;
-int pa_context_is_pending(struct pa_context *c);
+/** Create a new, unconnected stream with the specified name and sample type */
+struct pa_stream* pa_stream_new(struct pa_context *c, const char *name, const struct pa_sample_spec *ss);
-struct pa_stream* pa_stream_new(struct pa_context *c, enum pa_stream_direction dir, const char *dev, const char *name, const struct pa_sample_spec *ss, const struct pa_buffer_attr *attr, void (*complete) (struct pa_stream*s, int success, void *userdata), void *userdata);
+/** Decrease the reference counter by one */
void pa_stream_unref(struct pa_stream *s);
-struct pa_stream *pa_stream_ref(struct pa_stream *s);
-
-void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata);
-
-void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata);
-void pa_stream_set_write_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata);
-void pa_stream_write(struct pa_stream *p, const void *data, size_t length);
-size_t pa_stream_writable_size(struct pa_stream *p);
-
-void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata);
-
-int pa_stream_is_dead(struct pa_stream *p);
-int pa_stream_is_ready(struct pa_stream*p);
+/** Increase the reference counter by one */
+struct pa_stream *pa_stream_ref(struct pa_stream *s);
-void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata);
+/** Return the current state of the stream */
+enum pa_stream_state pa_stream_get_state(struct pa_stream *p);
+/** Return the context this stream is attached to */
struct pa_context* pa_stream_get_context(struct pa_stream *p);
+/** Return the device (sink input or source output) index this stream is connected to */
uint32_t pa_stream_get_index(struct pa_stream *s);
-struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata);
-void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata);
-
-void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-
-struct pa_sink_info {
- const char *name;
- uint32_t index;
- const char *description;
- struct pa_sample_spec sample_spec;
- uint32_t owner_module;
- uint32_t volume;
- uint32_t monitor_source;
- const char *monitor_source_name;
- uint32_t latency;
-};
-
-void pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-
-struct pa_source_info {
- const char *name;
- uint32_t index;
- const char *description;
- struct pa_sample_spec sample_spec;
- uint32_t owner_module;
- uint32_t monitor_of_sink;
- const char *monitor_of_sink_name;
-};
-
-void pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-
-struct pa_server_info {
- const char *user_name;
- const char *host_name;
- const char *server_version;
- const char *server_name;
- struct pa_sample_spec sample_spec;
-};
-
-void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata);
+/** Connect the stream to a sink */
+void pa_stream_connect_playback(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr);
-struct pa_module_info {
- uint32_t index;
- const char*name, *argument;
- uint32_t n_used, auto_unload;
-};
+/** Connect the stream to a source */
+void pa_stream_connect_record(struct pa_stream *s, const char *dev, const struct pa_buffer_attr *attr);
-void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata);
+/** Disconnect a stream from a source/sink */
+void pa_stream_disconnect(struct pa_stream *s);
-struct pa_client_info {
- uint32_t index;
- const char *name;
- uint32_t owner_module;
- const char *protocol_name;
-};
+/** Write some data to the server (for playback sinks), if free_cb is
+ * non-NULL this routine is called when all data has been written out
+ * and an internal reference to the specified data is kept, the data
+ * is not copied. If NULL, the data is copied into an internal
+ * buffer. */
+void pa_stream_write(struct pa_stream *p, const void *data, size_t length, void (*free_cb)(void *p));
-void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata);
-
-struct pa_sink_input_info {
- uint32_t index;
- const char *name;
- uint32_t owner_module;
- uint32_t owner_client;
- uint32_t sink;
- struct pa_sample_spec sample_spec;
- uint32_t volume;
- uint32_t latency;
-};
-
-void pa_context_get_sink_input_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_input_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata);
+/** Return the amount of bytes that may be written using pa_stream_write() */
+size_t pa_stream_writable_size(struct pa_stream *p);
-struct pa_source_output_info {
- uint32_t index;
- const char *name;
- uint32_t owner_module;
- uint32_t owner_client;
- uint32_t source;
- struct pa_sample_spec sample_spec;
-};
+/** Drain a playback stream */
+struct pa_operation* pa_stream_drain(struct pa_stream *s, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata);
-void pa_context_get_source_output_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_output_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata);
+/** Get the playback latency of a stream */
+struct pa_operation* pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata);
-void pa_context_set_sink_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-void pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
+/** Set the callback function that is called whenever the state of the stream changes */
+void pa_stream_set_state_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata);
-void pa_context_exit(struct pa_context *c);
-void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata);
+/** Set the callback function that is called when new data may be written to the stream */
+void pa_stream_set_write_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata);
-void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata);
+/** Set the callback function that is called when new data is available from the stream */
+void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata);
-#ifdef __cplusplus
-}
-#endif
+PA_C_DECL_END
#endif
diff --git a/polyp/polyplib-subscribe.c b/polyp/polyplib-subscribe.c
index 35001d3d..a14d0b06 100644
--- a/polyp/polyplib-subscribe.c
+++ b/polyp/polyplib-subscribe.c
@@ -23,1528 +23,52 @@
#include <config.h>
#endif
-#include <stdio.h>
#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include "polyplib.h"
-#include "native-common.h"
-#include "pdispatch.h"
-#include "pstream.h"
-#include "dynarray.h"
-#include "socket-client.h"
+#include "polyplib-subscribe.h"
+#include "polyplib-internal.h"
#include "pstream-util.h"
-#include "authkey.h"
-#include "util.h"
-#include "xmalloc.h"
-#define DEFAULT_MAXLENGTH 204800
-#define DEFAULT_TLENGTH 10240
-#define DEFAULT_PREBUF 4096
-#define DEFAULT_MINREQ 1024
-#define DEFAULT_FRAGSIZE 1024
-
-#define DEFAULT_TIMEOUT (5*60)
-#define DEFAULT_SERVER "/tmp/polypaudio/native"
-#define DEFAULT_PORT "4713"
-
-struct pa_context {
- char *name;
- struct pa_mainloop_api* mainloop;
- struct pa_socket_client *client;
- struct pa_pstream *pstream;
- struct pa_pdispatch *pdispatch;
- struct pa_dynarray *record_streams, *playback_streams;
- struct pa_stream *first_stream;
- uint32_t ctag;
- uint32_t error;
- enum {
- CONTEXT_UNCONNECTED,
- CONTEXT_CONNECTING,
- CONTEXT_AUTHORIZING,
- CONTEXT_SETTING_NAME,
- CONTEXT_READY,
- CONTEXT_DEAD
- } state;
-
- void (*connect_complete_callback)(struct pa_context*c, int success, void *userdata);
- void *connect_complete_userdata;
-
- void (*drain_complete_callback)(struct pa_context*c, void *userdata);
- void *drain_complete_userdata;
-
- void (*die_callback)(struct pa_context*c, void *userdata);
- void *die_userdata;
-
- void (*stat_callback)(struct pa_context*c, uint32_t count, uint32_t total, void *userdata);
- void *stat_userdata;
-
- void (*play_sample_callback)(struct pa_context*c, int success, void *userdata);
- void *play_sample_userdata;
-
- void (*remove_sample_callback)(struct pa_context*c, int success, void *userdata);
- void *remove_sample_userdata;
-
- void (*get_server_info_callback)(struct pa_context*c, const struct pa_server_info* i, void *userdata);
- void *get_server_info_userdata;
-
- void (*get_sink_info_callback)(struct pa_context*c, const struct pa_sink_info* i, int is_last, void *userdata);
- void *get_sink_info_userdata;
-
- void (*get_source_info_callback)(struct pa_context*c, const struct pa_source_info* i, int is_last, void *userdata);
- void *get_source_info_userdata;
-
- void (*subscribe_callback)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata);
- void *subscribe_userdata;
- enum pa_subscription_mask subscribe_mask;
-
- void (*get_client_info_callback)(struct pa_context*c, const struct pa_client_info* i, int is_last, void *userdata);
- void *get_client_info_userdata;
-
- void (*get_module_info_callback)(struct pa_context*c, const struct pa_module_info* i, int is_last, void *userdata);
- void *get_module_info_userdata;
-
- uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH];
-};
-
-struct pa_stream {
- struct pa_context *context;
- struct pa_stream *next, *previous;
-
- char *name;
- struct pa_buffer_attr buffer_attr;
- struct pa_sample_spec sample_spec;
- uint32_t channel;
- int channel_valid;
- uint32_t device_index;
- enum pa_stream_direction direction;
-
- enum { STREAM_CREATING, STREAM_READY, STREAM_DEAD} state;
- uint32_t requested_bytes;
-
- void (*read_callback)(struct pa_stream *p, const void*data, size_t length, void *userdata);
- void *read_userdata;
-
- void (*write_callback)(struct pa_stream *p, size_t length, void *userdata);
- void *write_userdata;
-
- void (*create_complete_callback)(struct pa_stream *s, int success, void *userdata);
- void *create_complete_userdata;
-
- void (*drain_complete_callback)(struct pa_stream *s, void *userdata);
- void *drain_complete_userdata;
-
- void (*die_callback)(struct pa_stream*c, void *userdata);
- void *die_userdata;
-
- void (*get_latency_callback)(struct pa_stream*c, uint32_t latency, void *userdata);
- void *get_latency_userdata;
-
- void (*finish_sample_callback)(struct pa_stream*c, int success, void *userdata);
- void *finish_sample_userdata;
-};
-
-static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-
-static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = {
- [PA_COMMAND_ERROR] = { NULL },
- [PA_COMMAND_REPLY] = { NULL },
- [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { NULL },
- [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { NULL },
- [PA_COMMAND_CREATE_RECORD_STREAM] = { NULL },
- [PA_COMMAND_DELETE_RECORD_STREAM] = { NULL },
- [PA_COMMAND_EXIT] = { NULL },
- [PA_COMMAND_REQUEST] = { command_request },
- [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { command_playback_stream_killed },
- [PA_COMMAND_RECORD_STREAM_KILLED] = { command_playback_stream_killed },
- [PA_COMMAND_SUBSCRIBE_EVENT] = { command_subscribe_event },
-};
-
-struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) {
- struct pa_context *c;
- assert(mainloop && name);
-
- c = pa_xmalloc(sizeof(struct pa_context));
- c->name = pa_xstrdup(name);
- c->mainloop = mainloop;
- c->client = NULL;
- c->pstream = NULL;
- c->pdispatch = NULL;
- c->playback_streams = pa_dynarray_new();
- assert(c->playback_streams);
- c->record_streams = pa_dynarray_new();
- assert(c->record_streams);
- c->first_stream = NULL;
- c->error = PA_ERROR_OK;
- c->state = CONTEXT_UNCONNECTED;
- c->ctag = 0;
-
- c->connect_complete_callback = NULL;
- c->connect_complete_userdata = NULL;
-
- c->drain_complete_callback = NULL;
- c->drain_complete_userdata = NULL;
-
- c->die_callback = NULL;
- c->die_userdata = NULL;
-
- c->stat_callback = NULL;
- c->stat_userdata = NULL;
-
- c->play_sample_callback = NULL;
- c->play_sample_userdata = NULL;
-
- c->remove_sample_callback = NULL;
- c->remove_sample_userdata = NULL;
-
- c->get_server_info_callback = NULL;
- c->get_server_info_userdata = NULL;
-
- c->get_sink_info_callback = NULL;
- c->get_sink_info_userdata = NULL;
-
- c->get_source_info_callback = NULL;
- c->get_source_info_userdata = NULL;
-
- c->subscribe_callback = NULL;
- c->subscribe_userdata = NULL;
-
- c->get_client_info_callback = NULL;
- c->get_client_info_userdata = NULL;
-
- c->get_module_info_callback = NULL;
- c->get_module_info_userdata = NULL;
-
- pa_check_for_sigpipe();
- return c;
-}
-
-void pa_context_free(struct pa_context *c) {
- assert(c);
-
- while (c->first_stream)
- pa_stream_free(c->first_stream);
-
- if (c->client)
- pa_socket_client_free(c->client);
- if (c->pdispatch)
- pa_pdispatch_free(c->pdispatch);
- if (c->pstream)
- pa_pstream_free(c->pstream);
- if (c->record_streams)
- pa_dynarray_free(c->record_streams, NULL, NULL);
- if (c->playback_streams)
- pa_dynarray_free(c->playback_streams, NULL, NULL);
-
- pa_xfree(c->name);
- pa_xfree(c);
-}
-
-static void stream_dead(struct pa_stream *s) {
- assert(s);
-
- if (s->state == STREAM_DEAD)
- return;
-
- if (s->state == STREAM_READY) {
- s->state = STREAM_DEAD;
- if (s->die_callback)
- s->die_callback(s, s->die_userdata);
- } else
- s->state = STREAM_DEAD;
-}
-
-static void context_dead(struct pa_context *c) {
- struct pa_stream *s;
- assert(c);
-
- if (c->state == CONTEXT_DEAD)
- return;
-
- if (c->pdispatch)
- pa_pdispatch_free(c->pdispatch);
- c->pdispatch = NULL;
-
- if (c->pstream)
- pa_pstream_free(c->pstream);
- c->pstream = NULL;
-
- if (c->client)
- pa_socket_client_free(c->client);
- c->client = NULL;
-
- for (s = c->first_stream; s; s = s->next)
- stream_dead(s);
-
- if (c->state == CONTEXT_READY) {
- c->state = CONTEXT_DEAD;
- if (c->die_callback)
- c->die_callback(c, c->die_userdata);
- } else
- c->state = CONTEXT_DEAD;
-}
-
-static void pstream_die_callback(struct pa_pstream *p, void *userdata) {
- struct pa_context *c = userdata;
- assert(p && c);
- c->error = PA_ERROR_CONNECTIONTERMINATED;
- context_dead(c);
-}
-
-static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) {
- struct pa_context *c = userdata;
- assert(p && packet && c);
-
- if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) {
- fprintf(stderr, "polyp.c: invalid packet.\n");
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- }
-}
-
-static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_stream *s;
- assert(p && chunk && c && chunk->memblock && chunk->memblock->data);
-
- if (!(s = pa_dynarray_get(c->record_streams, channel)))
- return;
-
- if (s->read_callback)
- s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata);
-}
-
-static int handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t) {
- assert(c && t);
-
- if (command == PA_COMMAND_ERROR) {
- if (pa_tagstruct_getu32(t, &c->error) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- return -1;
- }
-
- return 0;
- }
-
- c->error = (command == PA_COMMAND_TIMEOUT) ? PA_ERROR_TIMEOUT : PA_ERROR_INTERNAL;
- return -1;
-}
-
-static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c && (c->state == CONTEXT_AUTHORIZING || c->state == CONTEXT_SETTING_NAME));
-
- if (command != PA_COMMAND_REPLY) {
- handle_error(c, command, t);
- context_dead(c);
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 0, c->connect_complete_userdata);
-
- return;
- }
-
- if (c->state == CONTEXT_AUTHORIZING) {
- struct pa_tagstruct *t;
- c->state = CONTEXT_SETTING_NAME;
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_SET_NAME);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, c->name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c);
- } else {
- assert(c->state == CONTEXT_SETTING_NAME);
-
- c->state = CONTEXT_READY;
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 1, c->connect_complete_userdata);
- }
-
- return;
-}
-
-static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(client && c && c->state == CONTEXT_CONNECTING);
-
- pa_socket_client_free(client);
- c->client = NULL;
-
- if (!io) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- context_dead(c);
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 0, c->connect_complete_userdata);
-
- return;
- }
-
- c->pstream = pa_pstream_new(c->mainloop, io);
- assert(c->pstream);
- pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c);
- pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c);
- pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c);
-
- c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX);
- assert(c->pdispatch);
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_AUTH);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_put_arbitrary(t, c->auth_cookie, sizeof(c->auth_cookie));
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c);
- c->state = CONTEXT_AUTHORIZING;
-}
-
-static struct sockaddr *resolve_server(const char *server, size_t *len) {
- struct sockaddr *sa;
- struct addrinfo hints, *result = NULL;
- char *port;
- assert(server && len);
-
- if ((port = strrchr(server, ':')))
- port++;
- if (!port)
- port = DEFAULT_PORT;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = 0;
-
- if (getaddrinfo(server, port, &hints, &result) != 0)
- return NULL;
- assert(result);
-
- sa = pa_xmalloc(*len = result->ai_addrlen);
- memcpy(sa, result->ai_addr, *len);
-
- freeaddrinfo(result);
-
- return sa;
-}
-
-int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata) {
- assert(c && c->state == CONTEXT_UNCONNECTED);
-
- if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE, c->auth_cookie, sizeof(c->auth_cookie)) < 0) {
- c->error = PA_ERROR_AUTHKEY;
- return -1;
- }
-
- if (!server)
- if (!(server = getenv("POLYP_SERVER")))
- server = DEFAULT_SERVER;
-
- assert(!c->client);
-
- if (*server == '/') {
- if (!(c->client = pa_socket_client_new_unix(c->mainloop, server))) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- return -1;
- }
- } else {
- struct sockaddr* sa;
- size_t sa_len;
-
- if (!(sa = resolve_server(server, &sa_len))) {
- c->error = PA_ERROR_INVALIDSERVER;
- return -1;
- }
-
- c->client = pa_socket_client_new_sockaddr(c->mainloop, sa, sa_len);
- pa_xfree(sa);
-
- if (!c->client) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- return -1;
- }
- }
-
- c->connect_complete_callback = complete;
- c->connect_complete_userdata = userdata;
-
- pa_socket_client_set_callback(c->client, on_connection, c);
- c->state = CONTEXT_CONNECTING;
-
- return 0;
-}
-
-int pa_context_is_dead(struct pa_context *c) {
- assert(c);
- return c->state == CONTEXT_DEAD;
-}
-
-int pa_context_is_ready(struct pa_context *c) {
- assert(c);
- return c->state == CONTEXT_READY;
-}
-
-int pa_context_errno(struct pa_context *c) {
- assert(c);
- return c->error;
-}
-
-void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata) {
- assert(c);
- c->die_callback = cb;
- c->die_userdata = userdata;
-}
-
-static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_stream *s;
- uint32_t channel;
- assert(pd && (command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED) && t && c);
-
- if (pa_tagstruct_getu32(t, &channel) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel)))
- return;
-
- c->error = PA_ERROR_KILLED;
- stream_dead(s);
-}
-
-static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s;
- struct pa_context *c = userdata;
- uint32_t bytes, channel;
- assert(pd && command == PA_COMMAND_REQUEST && t && c);
-
- if (pa_tagstruct_getu32(t, &channel) < 0 ||
- pa_tagstruct_getu32(t, &bytes) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (!(s = pa_dynarray_get(c->playback_streams, channel)))
- return;
-
- if (s->state != STREAM_READY)
- return;
-
- s->requested_bytes += bytes;
-
- if (s->requested_bytes && s->write_callback)
- s->write_callback(s, s->requested_bytes, s->write_userdata);
-}
-
-static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s && s->state == STREAM_CREATING);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- stream_dead(s);
- if (s->create_complete_callback)
- s->create_complete_callback(s, 0, s->create_complete_userdata);
-
- return;
- }
-
- if (pa_tagstruct_getu32(t, &s->channel) < 0 ||
- ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) ||
- !pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- s->channel_valid = 1;
- pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s);
-
- s->state = STREAM_READY;
- if (s->create_complete_callback)
- s->create_complete_callback(s, 1, s->create_complete_userdata);
-}
-
-static void create_stream(struct pa_stream *s, const char *dev) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(s);
-
- s->state = STREAM_CREATING;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM);
- pa_tagstruct_putu32(t, tag = s->context->ctag++);
- pa_tagstruct_puts(t, s->name);
- pa_tagstruct_put_sample_spec(t, &s->sample_spec);
- pa_tagstruct_putu32(t, (uint32_t) -1);
- pa_tagstruct_puts(t, dev ? dev : "");
- pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
- if (s->direction == PA_STREAM_PLAYBACK) {
- pa_tagstruct_putu32(t, s->buffer_attr.tlength);
- pa_tagstruct_putu32(t, s->buffer_attr.prebuf);
- pa_tagstruct_putu32(t, s->buffer_attr.minreq);
- } else
- pa_tagstruct_putu32(t, s->buffer_attr.fragsize);
-
- pa_pstream_send_tagstruct(s->context->pstream, t);
- pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s);
-}
-
-static struct pa_stream *internal_stream_new(struct pa_context *c) {
- struct pa_stream *s;
-
- s = pa_xmalloc(sizeof(struct pa_stream));
- s->context = c;
-
- s->read_callback = NULL;
- s->read_userdata = NULL;
- s->write_callback = NULL;
- s->write_userdata = NULL;
- s->die_callback = NULL;
- s->die_userdata = NULL;
- s->create_complete_callback = NULL;
- s->create_complete_userdata = NULL;
- s->get_latency_callback = NULL;
- s->get_latency_userdata = NULL;
- s->finish_sample_callback = NULL;
- s->finish_sample_userdata = NULL;
-
- s->name = NULL;
- s->state = STREAM_CREATING;
- s->requested_bytes = 0;
- s->channel = 0;
- s->channel_valid = 0;
- s->device_index = (uint32_t) -1;
-
- memset(&s->buffer_attr, 0, sizeof(s->buffer_attr));
-
- s->next = c->first_stream;
- if (s->next)
- s->next->previous = s;
- s->previous = NULL;
- c->first_stream = s;
-
- return s;
-}
-
-struct pa_stream* pa_stream_new(
- struct pa_context *c,
- enum pa_stream_direction dir,
- const char *dev,
- const char *name,
- const struct pa_sample_spec *ss,
- const struct pa_buffer_attr *attr,
- void (*complete) (struct pa_stream*s, int success, void *userdata),
- void *userdata) {
-
- struct pa_stream *s;
-
- assert(c && name && ss && c->state == CONTEXT_READY && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD));
-
- s = internal_stream_new(c);
- assert(s);
-
- s->create_complete_callback = complete;
- s->create_complete_userdata = userdata;
- s->name = pa_xstrdup(name);
- s->state = STREAM_CREATING;
- s->direction = dir;
- s->sample_spec = *ss;
- if (attr)
- s->buffer_attr = *attr;
- else {
- s->buffer_attr.maxlength = DEFAULT_MAXLENGTH;
- s->buffer_attr.tlength = DEFAULT_TLENGTH;
- s->buffer_attr.prebuf = DEFAULT_PREBUF;
- s->buffer_attr.minreq = DEFAULT_MINREQ;
- s->buffer_attr.fragsize = DEFAULT_FRAGSIZE;
- }
-
- create_stream(s, dev);
-
- return s;
-}
-
-void pa_stream_free(struct pa_stream *s) {
- assert(s && s->context);
-
- if (s->context->pdispatch)
- pa_pdispatch_unregister_reply(s->context->pdispatch, s);
-
- pa_xfree(s->name);
-
- if (s->channel_valid && s->context->state == CONTEXT_READY) {
- struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM :
- (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM));
- pa_tagstruct_putu32(t, s->context->ctag++);
- pa_tagstruct_putu32(t, s->channel);
- pa_pstream_send_tagstruct(s->context->pstream, t);
- }
-
- if (s->channel_valid)
- pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL);
-
- if (s->next)
- s->next->previous = s->previous;
- if (s->previous)
- s->previous->next = s->next;
- else
- s->context->first_stream = s->next;
-
- pa_xfree(s);
-}
-
-void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) {
- s->write_callback = cb;
- s->write_userdata = userdata;
-}
-
-void pa_stream_write(struct pa_stream *s, const void *data, size_t length) {
- struct pa_memchunk chunk;
- assert(s && s->context && data && length && s->state == STREAM_READY);
-
- chunk.memblock = pa_memblock_new(length);
- assert(chunk.memblock && chunk.memblock->data);
- memcpy(chunk.memblock->data, data, length);
- chunk.index = 0;
- chunk.length = length;
-
- pa_pstream_send_memblock(s->context->pstream, s->channel, 0, &chunk);
- pa_memblock_unref(chunk.memblock);
-
- /*fprintf(stderr, "Sent %u bytes\n", length);*/
-
- if (length < s->requested_bytes)
- s->requested_bytes -= length;
- else
- s->requested_bytes = 0;
-}
-
-size_t pa_stream_writable_size(struct pa_stream *s) {
- assert(s && s->state == STREAM_READY);
- return s->requested_bytes;
-}
-
-void pa_stream_set_read_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) {
- assert(s && cb);
- s->read_callback = cb;
- s->read_userdata = userdata;
-}
-
-int pa_stream_is_dead(struct pa_stream *s) {
- return s->state == STREAM_DEAD;
-}
-
-int pa_stream_is_ready(struct pa_stream*s) {
- return s->state == STREAM_READY;
-}
-
-void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata) {
- assert(s);
- s->die_callback = cb;
- s->die_userdata = userdata;
-}
-
-int pa_context_is_pending(struct pa_context *c) {
- assert(c);
-
- if (c->state != CONTEXT_READY)
- return 0;
-
- return pa_pstream_is_pending(c->pstream) || pa_pdispatch_is_pending(c->pdispatch);
-}
-
-struct pa_context* pa_stream_get_context(struct pa_stream *p) {
- assert(p);
- return p->context;
-}
-
-static void set_dispatch_callbacks(struct pa_context *c);
-
-static void pdispatch_drain_callback(struct pa_pdispatch*pd, void *userdata) {
- set_dispatch_callbacks(userdata);
-}
-
-static void pstream_drain_callback(struct pa_pstream *s, void *userdata) {
- set_dispatch_callbacks(userdata);
-}
-
-static void set_dispatch_callbacks(struct pa_context *c) {
- assert(c && c->state == CONTEXT_READY);
-
- pa_pstream_set_drain_callback(c->pstream, NULL, NULL);
- pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL);
-
- if (pa_pdispatch_is_pending(c->pdispatch)) {
- pa_pdispatch_set_drain_callback(c->pdispatch, pdispatch_drain_callback, c);
- return;
- }
-
- if (pa_pstream_is_pending(c->pstream)) {
- pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c);
- return;
- }
-
- assert(c->drain_complete_callback);
- c->drain_complete_callback(c, c->drain_complete_userdata);
-}
-
-int pa_context_drain(
- struct pa_context *c,
- void (*complete) (struct pa_context*c, void *userdata),
- void *userdata) {
-
- assert(c && c->state == CONTEXT_READY);
-
- if (complete == NULL) {
- c->drain_complete_callback = NULL;
- pa_pstream_set_drain_callback(c->pstream, NULL, NULL);
- pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL);
- return 0;
- }
-
- if (!pa_context_is_pending(c))
- return -1;
-
- c->drain_complete_callback = complete;
- c->drain_complete_userdata = userdata;
-
- set_dispatch_callbacks(c);
-
- return 0;
-}
-
-static void stream_drain_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- stream_dead(s);
- return;
- }
-
- if (s->state != STREAM_READY)
- return;
-
- if (!pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->drain_complete_callback) {
- void (*temp) (struct pa_stream*s, void *userdata) = s->drain_complete_callback;
- s->drain_complete_callback = NULL;
- temp(s, s->drain_complete_userdata);
- }
-}
-
-
-void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(s && s->state == STREAM_READY);
-
- if (!complete) {
- s->drain_complete_callback = NULL;
- return;
- }
-
- s->drain_complete_callback = complete;
- s->drain_complete_userdata = userdata;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, PA_COMMAND_DRAIN_PLAYBACK_STREAM);
- pa_tagstruct_putu32(t, tag = s->context->ctag++);
- pa_tagstruct_putu32(t, s->channel);
- pa_pstream_send_tagstruct(s->context->pstream, t);
- pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_drain_callback, s);
-}
-
-void pa_context_exit(struct pa_context *c) {
- struct pa_tagstruct *t;
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_EXIT);
- pa_tagstruct_putu32(t, c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
-}
-
-static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- uint32_t total, count;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->stat_callback)
- c->stat_callback(c, (uint32_t) -1, (uint32_t) -1, c->stat_userdata);
- return;
- }
-
- if (pa_tagstruct_getu32(t, &count) < 0 ||
- pa_tagstruct_getu32(t, &total) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->stat_callback)
- c->stat_callback(c, count, total, c->stat_userdata);
-}
-
-void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata) {
- uint32_t tag;
- struct pa_tagstruct *t;
-
- c->stat_callback = cb;
- c->stat_userdata = userdata;
-
- if (cb == NULL)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_STAT);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_stat_callback, c);
-}
-
-static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- uint32_t latency;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- if (s->get_latency_callback)
- s->get_latency_callback(s, (uint32_t) -1, s->get_latency_userdata);
- return;
- }
-
- if (pa_tagstruct_getu32(t, &latency) < 0 ||
- !pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->get_latency_callback)
- s->get_latency_callback(s, latency, s->get_latency_userdata);
-}
-
-void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata) {
- uint32_t tag;
- struct pa_tagstruct *t;
-
- p->get_latency_callback = cb;
- p->get_latency_userdata = userdata;
-
- if (cb == NULL)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY);
- pa_tagstruct_putu32(t, tag = p->context->ctag++);
- pa_tagstruct_putu32(t, p->channel);
- pa_pstream_send_tagstruct(p->context->pstream, t);
- pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, p);
-}
-
-struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) {
- struct pa_stream *s;
- struct pa_tagstruct *t;
- uint32_t tag;
-
- s = internal_stream_new(c);
- assert(s);
-
- s->create_complete_callback = cb;
- s->create_complete_userdata = userdata;
- s->name = pa_xstrdup(name);
- s->state = STREAM_CREATING;
- s->direction = PA_STREAM_UPLOAD;
- s->sample_spec = *ss;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_CREATE_UPLOAD_STREAM);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, name);
- pa_tagstruct_put_sample_spec(t, ss);
- pa_tagstruct_putu32(t, length);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s);
-
- return s;
-}
-
-static void stream_finish_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- if (s->finish_sample_callback)
- s->finish_sample_callback(s, 0, s->finish_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->finish_sample_callback)
- s->finish_sample_callback(s, 1, s->finish_sample_userdata);
-}
-
-void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(p);
-
- p->finish_sample_callback = cb;
- p->finish_sample_userdata = userdata;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_FINISH_UPLOAD_STREAM);
- pa_tagstruct_putu32(t, tag = p->context->ctag++);
- pa_tagstruct_putu32(t, p->channel);
- pa_pstream_send_tagstruct(p->context->pstream, t);
- pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_finish_sample_callback, p);
-}
-
-static void context_play_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->play_sample_callback)
- c->play_sample_callback(c, 0, c->play_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->play_sample_callback)
- c->play_sample_callback(c, 1, c->play_sample_userdata);
-}
-
-void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c && name && *name && (!dev || *dev));
-
- c->play_sample_callback = cb;
- c->play_sample_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_PLAY_SAMPLE);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, (uint32_t) -1);
- pa_tagstruct_puts(t, dev ? dev : "");
- pa_tagstruct_putu32(t, volume);
- pa_tagstruct_puts(t, name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_play_sample_callback, c);
-}
-
-static void context_remove_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->remove_sample_callback)
- c->remove_sample_callback(c, 0, c->remove_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->remove_sample_callback)
- c->remove_sample_callback(c, 1, c->remove_sample_userdata);
-}
-
-void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c && name);
-
- c->remove_sample_callback = cb;
- c->remove_sample_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_SAMPLE);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_remove_sample_callback, c);
-}
-
-static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_server_info i;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_server_info_callback)
- c->get_server_info_callback(c, NULL, c->get_server_info_userdata);
- return;
- }
-
- if (pa_tagstruct_gets(t, &i.server_name) < 0 ||
- pa_tagstruct_gets(t, &i.server_version) < 0 ||
- pa_tagstruct_gets(t, &i.user_name) < 0 ||
- pa_tagstruct_gets(t, &i.host_name) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_server_info_callback)
- c->get_server_info_callback(c, &i, c->get_server_info_userdata);
-}
-
-void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_server_info_callback = cb;
- c->get_server_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SERVER_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_server_info_callback, c);
-}
-
-static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, NULL, 0, c->get_sink_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_sink_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.description) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
- pa_tagstruct_getu32(t, &i.volume) < 0 ||
- pa_tagstruct_getu32(t, &i.monitor_source) < 0 ||
- pa_tagstruct_gets(t, &i.monitor_source_name) < 0 ||
- pa_tagstruct_getu32(t, &i.latency) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, &i, 0, c->get_sink_info_userdata);
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, NULL, 1, c->get_sink_info_userdata);
-}
-
-void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_sink_info_callback = cb;
- c->get_sink_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c);
-}
-
-static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, NULL, 0, c->get_source_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_source_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.description) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
- pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 ||
- pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, &i, 0, c->get_source_info_userdata);
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, NULL, 1, c->get_source_info_userdata);
-}
-
-void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_source_info_callback = cb;
- c->get_source_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c);
-}
-
-void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- assert(c);
-
- c->subscribe_callback = cb;
- c->subscribe_userdata = userdata;
- c->subscribe_mask = m;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE);
- pa_tagstruct_putu32(t, c->ctag++);
- pa_tagstruct_putu32(t, cb ? m : 0);
- pa_pstream_send_tagstruct(c->pstream, t);
-}
-
-static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
+void pa_command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
struct pa_context *c = userdata;
enum pa_subscription_event_type e;
uint32_t index;
assert(pd && command == PA_COMMAND_SUBSCRIBE_EVENT && t && c);
+ pa_context_ref(c);
+
if (pa_tagstruct_getu32(t, &e) < 0 ||
pa_tagstruct_getu32(t, &index) < 0 ||
!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
+ pa_context_fail(c, PA_ERROR_PROTOCOL);
+ goto finish;
}
- if (pa_subscription_match_flags(c->subscribe_mask, e) && c->subscribe_callback)
+ if (c->subscribe_callback)
c->subscribe_callback(c, e, index, c->subscribe_userdata);
-}
-
-void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_sink_info_callback = cb;
- c->get_sink_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_tagstruct_puts(t, "");
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c);
-}
-
-void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_source_info_callback = cb;
- c->get_source_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_tagstruct_puts(t, "");
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c);
-}
-
-static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, NULL, 0, c->get_client_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_client_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.protocol_name) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, &i, 0, c->get_client_info_userdata);
- }
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, NULL, 1, c->get_client_info_userdata);
+finish:
+ pa_context_unref(c);
}
-void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
+struct pa_operation* pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
+ struct pa_operation *o;
struct pa_tagstruct *t;
uint32_t tag;
assert(c);
- c->get_client_info_callback = cb;
- c->get_client_info_userdata = userdata;
+ o = pa_operation_new(c, NULL);
+ o->callback = cb;
+ o->userdata = userdata;
- if (!cb)
- return;
-
t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c);
-}
-
-void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_client_info_callback = cb;
- c->get_client_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO_LIST);
+ pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE);
pa_tagstruct_putu32(t, tag = c->ctag++);
+ pa_tagstruct_putu32(t, cb ? m : 0);
pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c);
-}
-
-static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, NULL, 0, c->get_module_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_module_info i;
+ pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, o);
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.argument) < 0 ||
- pa_tagstruct_getu32(t, &i.n_used) < 0 ||
- pa_tagstruct_getu32(t, &i.auto_unload) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, &i, 0, c->get_module_info_userdata);
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, NULL, 1, c->get_module_info_userdata);
+ return pa_operation_ref(o);
}
-void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_module_info_callback = cb;
- c->get_module_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c);
-}
-
-void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_module_info_callback = cb;
- c->get_module_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c);
-}
diff --git a/polyp/polyplib-subscribe.h b/polyp/polyplib-subscribe.h
index a0dd9f9c..56384915 100644
--- a/polyp/polyplib-subscribe.h
+++ b/polyp/polyplib-subscribe.h
@@ -1,5 +1,5 @@
-#ifndef foopolyplibhfoo
-#define foopolyplibhfoo
+#ifndef foopolyplibsubscribehfoo
+#define foopolyplibsubscribehfoo
/* $Id$ */
@@ -22,157 +22,17 @@
USA.
***/
-#include <sys/types.h>
+#include <inttypes.h>
-#include "sample.h"
#include "polyplib-def.h"
-#include "mainloop-api.h"
+#include "polyplib-context.h"
+#include "cdecl.h"
-#ifdef __cplusplus
-//extern "C" {
-#endif
-
-struct pa_context;
-struct pa_stream;
-
-struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name);
-void pa_context_unref(struct pa_context *c);
-struct pa_context* pa_context_ref(struct pa_context *c);
-
-int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata);
-int pa_context_drain(struct pa_context *c, void (*complete) (struct pa_context*c, void *userdata), void *userdata);
-void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata);
-
-int pa_context_is_dead(struct pa_context *c);
-int pa_context_is_ready(struct pa_context *c);
-int pa_context_errno(struct pa_context *c);
-
-int pa_context_is_pending(struct pa_context *c);
-
-struct pa_stream* pa_stream_new(struct pa_context *c, enum pa_stream_direction dir, const char *dev, const char *name, const struct pa_sample_spec *ss, const struct pa_buffer_attr *attr, void (*complete) (struct pa_stream*s, int success, void *userdata), void *userdata);
-void pa_stream_unref(struct pa_stream *s);
-struct pa_stream *pa_stream_ref(struct pa_stream *s);
-
-void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata);
-
-void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata);
-
-void pa_stream_set_write_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata);
-void pa_stream_write(struct pa_stream *p, const void *data, size_t length);
-size_t pa_stream_writable_size(struct pa_stream *p);
-
-void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata);
-
-int pa_stream_is_dead(struct pa_stream *p);
-int pa_stream_is_ready(struct pa_stream*p);
-
-void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata);
-
-struct pa_context* pa_stream_get_context(struct pa_stream *p);
-
-uint32_t pa_stream_get_index(struct pa_stream *s);
-
-struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata);
-void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata);
-
-void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
+PA_C_DECL_BEGIN
-struct pa_sink_info {
- const char *name;
- uint32_t index;
- const char *description;
- struct pa_sample_spec sample_spec;
- uint32_t owner_module;
- uint32_t volume;
- uint32_t monitor_source;
- const char *monitor_source_name;
- uint32_t latency;
-};
+struct pa_operation* pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
+void pa_context_set_subscribe_callback(struct pa_context *c, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata);
-void pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-
-struct pa_source_info {
- const char *name;
- uint32_t index;
- const char *description;
- struct pa_sample_spec sample_spec;
- uint32_t owner_module;
- uint32_t monitor_of_sink;
- const char *monitor_of_sink_name;
-};
-
-void pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-
-struct pa_server_info {
- const char *user_name;
- const char *host_name;
- const char *server_version;
- const char *server_name;
- struct pa_sample_spec sample_spec;
-};
-
-void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata);
-
-struct pa_module_info {
- uint32_t index;
- const char*name, *argument;
- uint32_t n_used, auto_unload;
-};
-
-void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata);
-
-struct pa_client_info {
- uint32_t index;
- const char *name;
- uint32_t owner_module;
- const char *protocol_name;
-};
-
-void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata);
-
-struct pa_sink_input_info {
- uint32_t index;
- const char *name;
- uint32_t owner_module;
- uint32_t owner_client;
- uint32_t sink;
- struct pa_sample_spec sample_spec;
- uint32_t volume;
- uint32_t latency;
-};
-
-void pa_context_get_sink_input_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_input_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata);
-
-struct pa_source_output_info {
- uint32_t index;
- const char *name;
- uint32_t owner_module;
- uint32_t owner_client;
- uint32_t source;
- struct pa_sample_spec sample_spec;
-};
-
-void pa_context_get_source_output_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_output_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata);
-
-void pa_context_set_sink_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-void pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-
-void pa_context_exit(struct pa_context *c);
-void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata);
-
-void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata);
-
-#ifdef __cplusplus
-}
-#endif
+PA_C_DECL_END
#endif
diff --git a/polyp/polyplib.c b/polyp/polyplib.c
deleted file mode 100644
index 35001d3d..00000000
--- a/polyp/polyplib.c
+++ /dev/null
@@ -1,1550 +0,0 @@
-/* $Id$ */
-
-/***
- This file is part of polypaudio.
-
- polypaudio is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2 of the License,
- or (at your option) any later version.
-
- polypaudio 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 polypaudio; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- USA.
-***/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-
-#include "polyplib.h"
-#include "native-common.h"
-#include "pdispatch.h"
-#include "pstream.h"
-#include "dynarray.h"
-#include "socket-client.h"
-#include "pstream-util.h"
-#include "authkey.h"
-#include "util.h"
-#include "xmalloc.h"
-
-#define DEFAULT_MAXLENGTH 204800
-#define DEFAULT_TLENGTH 10240
-#define DEFAULT_PREBUF 4096
-#define DEFAULT_MINREQ 1024
-#define DEFAULT_FRAGSIZE 1024
-
-#define DEFAULT_TIMEOUT (5*60)
-#define DEFAULT_SERVER "/tmp/polypaudio/native"
-#define DEFAULT_PORT "4713"
-
-struct pa_context {
- char *name;
- struct pa_mainloop_api* mainloop;
- struct pa_socket_client *client;
- struct pa_pstream *pstream;
- struct pa_pdispatch *pdispatch;
- struct pa_dynarray *record_streams, *playback_streams;
- struct pa_stream *first_stream;
- uint32_t ctag;
- uint32_t error;
- enum {
- CONTEXT_UNCONNECTED,
- CONTEXT_CONNECTING,
- CONTEXT_AUTHORIZING,
- CONTEXT_SETTING_NAME,
- CONTEXT_READY,
- CONTEXT_DEAD
- } state;
-
- void (*connect_complete_callback)(struct pa_context*c, int success, void *userdata);
- void *connect_complete_userdata;
-
- void (*drain_complete_callback)(struct pa_context*c, void *userdata);
- void *drain_complete_userdata;
-
- void (*die_callback)(struct pa_context*c, void *userdata);
- void *die_userdata;
-
- void (*stat_callback)(struct pa_context*c, uint32_t count, uint32_t total, void *userdata);
- void *stat_userdata;
-
- void (*play_sample_callback)(struct pa_context*c, int success, void *userdata);
- void *play_sample_userdata;
-
- void (*remove_sample_callback)(struct pa_context*c, int success, void *userdata);
- void *remove_sample_userdata;
-
- void (*get_server_info_callback)(struct pa_context*c, const struct pa_server_info* i, void *userdata);
- void *get_server_info_userdata;
-
- void (*get_sink_info_callback)(struct pa_context*c, const struct pa_sink_info* i, int is_last, void *userdata);
- void *get_sink_info_userdata;
-
- void (*get_source_info_callback)(struct pa_context*c, const struct pa_source_info* i, int is_last, void *userdata);
- void *get_source_info_userdata;
-
- void (*subscribe_callback)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata);
- void *subscribe_userdata;
- enum pa_subscription_mask subscribe_mask;
-
- void (*get_client_info_callback)(struct pa_context*c, const struct pa_client_info* i, int is_last, void *userdata);
- void *get_client_info_userdata;
-
- void (*get_module_info_callback)(struct pa_context*c, const struct pa_module_info* i, int is_last, void *userdata);
- void *get_module_info_userdata;
-
- uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH];
-};
-
-struct pa_stream {
- struct pa_context *context;
- struct pa_stream *next, *previous;
-
- char *name;
- struct pa_buffer_attr buffer_attr;
- struct pa_sample_spec sample_spec;
- uint32_t channel;
- int channel_valid;
- uint32_t device_index;
- enum pa_stream_direction direction;
-
- enum { STREAM_CREATING, STREAM_READY, STREAM_DEAD} state;
- uint32_t requested_bytes;
-
- void (*read_callback)(struct pa_stream *p, const void*data, size_t length, void *userdata);
- void *read_userdata;
-
- void (*write_callback)(struct pa_stream *p, size_t length, void *userdata);
- void *write_userdata;
-
- void (*create_complete_callback)(struct pa_stream *s, int success, void *userdata);
- void *create_complete_userdata;
-
- void (*drain_complete_callback)(struct pa_stream *s, void *userdata);
- void *drain_complete_userdata;
-
- void (*die_callback)(struct pa_stream*c, void *userdata);
- void *die_userdata;
-
- void (*get_latency_callback)(struct pa_stream*c, uint32_t latency, void *userdata);
- void *get_latency_userdata;
-
- void (*finish_sample_callback)(struct pa_stream*c, int success, void *userdata);
- void *finish_sample_userdata;
-};
-
-static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata);
-
-static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = {
- [PA_COMMAND_ERROR] = { NULL },
- [PA_COMMAND_REPLY] = { NULL },
- [PA_COMMAND_CREATE_PLAYBACK_STREAM] = { NULL },
- [PA_COMMAND_DELETE_PLAYBACK_STREAM] = { NULL },
- [PA_COMMAND_CREATE_RECORD_STREAM] = { NULL },
- [PA_COMMAND_DELETE_RECORD_STREAM] = { NULL },
- [PA_COMMAND_EXIT] = { NULL },
- [PA_COMMAND_REQUEST] = { command_request },
- [PA_COMMAND_PLAYBACK_STREAM_KILLED] = { command_playback_stream_killed },
- [PA_COMMAND_RECORD_STREAM_KILLED] = { command_playback_stream_killed },
- [PA_COMMAND_SUBSCRIBE_EVENT] = { command_subscribe_event },
-};
-
-struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name) {
- struct pa_context *c;
- assert(mainloop && name);
-
- c = pa_xmalloc(sizeof(struct pa_context));
- c->name = pa_xstrdup(name);
- c->mainloop = mainloop;
- c->client = NULL;
- c->pstream = NULL;
- c->pdispatch = NULL;
- c->playback_streams = pa_dynarray_new();
- assert(c->playback_streams);
- c->record_streams = pa_dynarray_new();
- assert(c->record_streams);
- c->first_stream = NULL;
- c->error = PA_ERROR_OK;
- c->state = CONTEXT_UNCONNECTED;
- c->ctag = 0;
-
- c->connect_complete_callback = NULL;
- c->connect_complete_userdata = NULL;
-
- c->drain_complete_callback = NULL;
- c->drain_complete_userdata = NULL;
-
- c->die_callback = NULL;
- c->die_userdata = NULL;
-
- c->stat_callback = NULL;
- c->stat_userdata = NULL;
-
- c->play_sample_callback = NULL;
- c->play_sample_userdata = NULL;
-
- c->remove_sample_callback = NULL;
- c->remove_sample_userdata = NULL;
-
- c->get_server_info_callback = NULL;
- c->get_server_info_userdata = NULL;
-
- c->get_sink_info_callback = NULL;
- c->get_sink_info_userdata = NULL;
-
- c->get_source_info_callback = NULL;
- c->get_source_info_userdata = NULL;
-
- c->subscribe_callback = NULL;
- c->subscribe_userdata = NULL;
-
- c->get_client_info_callback = NULL;
- c->get_client_info_userdata = NULL;
-
- c->get_module_info_callback = NULL;
- c->get_module_info_userdata = NULL;
-
- pa_check_for_sigpipe();
- return c;
-}
-
-void pa_context_free(struct pa_context *c) {
- assert(c);
-
- while (c->first_stream)
- pa_stream_free(c->first_stream);
-
- if (c->client)
- pa_socket_client_free(c->client);
- if (c->pdispatch)
- pa_pdispatch_free(c->pdispatch);
- if (c->pstream)
- pa_pstream_free(c->pstream);
- if (c->record_streams)
- pa_dynarray_free(c->record_streams, NULL, NULL);
- if (c->playback_streams)
- pa_dynarray_free(c->playback_streams, NULL, NULL);
-
- pa_xfree(c->name);
- pa_xfree(c);
-}
-
-static void stream_dead(struct pa_stream *s) {
- assert(s);
-
- if (s->state == STREAM_DEAD)
- return;
-
- if (s->state == STREAM_READY) {
- s->state = STREAM_DEAD;
- if (s->die_callback)
- s->die_callback(s, s->die_userdata);
- } else
- s->state = STREAM_DEAD;
-}
-
-static void context_dead(struct pa_context *c) {
- struct pa_stream *s;
- assert(c);
-
- if (c->state == CONTEXT_DEAD)
- return;
-
- if (c->pdispatch)
- pa_pdispatch_free(c->pdispatch);
- c->pdispatch = NULL;
-
- if (c->pstream)
- pa_pstream_free(c->pstream);
- c->pstream = NULL;
-
- if (c->client)
- pa_socket_client_free(c->client);
- c->client = NULL;
-
- for (s = c->first_stream; s; s = s->next)
- stream_dead(s);
-
- if (c->state == CONTEXT_READY) {
- c->state = CONTEXT_DEAD;
- if (c->die_callback)
- c->die_callback(c, c->die_userdata);
- } else
- c->state = CONTEXT_DEAD;
-}
-
-static void pstream_die_callback(struct pa_pstream *p, void *userdata) {
- struct pa_context *c = userdata;
- assert(p && c);
- c->error = PA_ERROR_CONNECTIONTERMINATED;
- context_dead(c);
-}
-
-static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) {
- struct pa_context *c = userdata;
- assert(p && packet && c);
-
- if (pa_pdispatch_run(c->pdispatch, packet, c) < 0) {
- fprintf(stderr, "polyp.c: invalid packet.\n");
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- }
-}
-
-static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, int32_t delta, const struct pa_memchunk *chunk, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_stream *s;
- assert(p && chunk && c && chunk->memblock && chunk->memblock->data);
-
- if (!(s = pa_dynarray_get(c->record_streams, channel)))
- return;
-
- if (s->read_callback)
- s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata);
-}
-
-static int handle_error(struct pa_context *c, uint32_t command, struct pa_tagstruct *t) {
- assert(c && t);
-
- if (command == PA_COMMAND_ERROR) {
- if (pa_tagstruct_getu32(t, &c->error) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- return -1;
- }
-
- return 0;
- }
-
- c->error = (command == PA_COMMAND_TIMEOUT) ? PA_ERROR_TIMEOUT : PA_ERROR_INTERNAL;
- return -1;
-}
-
-static void setup_complete_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c && (c->state == CONTEXT_AUTHORIZING || c->state == CONTEXT_SETTING_NAME));
-
- if (command != PA_COMMAND_REPLY) {
- handle_error(c, command, t);
- context_dead(c);
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 0, c->connect_complete_userdata);
-
- return;
- }
-
- if (c->state == CONTEXT_AUTHORIZING) {
- struct pa_tagstruct *t;
- c->state = CONTEXT_SETTING_NAME;
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_SET_NAME);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, c->name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c);
- } else {
- assert(c->state == CONTEXT_SETTING_NAME);
-
- c->state = CONTEXT_READY;
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 1, c->connect_complete_userdata);
- }
-
- return;
-}
-
-static void on_connection(struct pa_socket_client *client, struct pa_iochannel*io, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(client && c && c->state == CONTEXT_CONNECTING);
-
- pa_socket_client_free(client);
- c->client = NULL;
-
- if (!io) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- context_dead(c);
-
- if (c->connect_complete_callback)
- c->connect_complete_callback(c, 0, c->connect_complete_userdata);
-
- return;
- }
-
- c->pstream = pa_pstream_new(c->mainloop, io);
- assert(c->pstream);
- pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c);
- pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c);
- pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c);
-
- c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX);
- assert(c->pdispatch);
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_AUTH);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_put_arbitrary(t, c->auth_cookie, sizeof(c->auth_cookie));
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c);
- c->state = CONTEXT_AUTHORIZING;
-}
-
-static struct sockaddr *resolve_server(const char *server, size_t *len) {
- struct sockaddr *sa;
- struct addrinfo hints, *result = NULL;
- char *port;
- assert(server && len);
-
- if ((port = strrchr(server, ':')))
- port++;
- if (!port)
- port = DEFAULT_PORT;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = 0;
-
- if (getaddrinfo(server, port, &hints, &result) != 0)
- return NULL;
- assert(result);
-
- sa = pa_xmalloc(*len = result->ai_addrlen);
- memcpy(sa, result->ai_addr, *len);
-
- freeaddrinfo(result);
-
- return sa;
-}
-
-int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata) {
- assert(c && c->state == CONTEXT_UNCONNECTED);
-
- if (pa_authkey_load_from_home(PA_NATIVE_COOKIE_FILE, c->auth_cookie, sizeof(c->auth_cookie)) < 0) {
- c->error = PA_ERROR_AUTHKEY;
- return -1;
- }
-
- if (!server)
- if (!(server = getenv("POLYP_SERVER")))
- server = DEFAULT_SERVER;
-
- assert(!c->client);
-
- if (*server == '/') {
- if (!(c->client = pa_socket_client_new_unix(c->mainloop, server))) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- return -1;
- }
- } else {
- struct sockaddr* sa;
- size_t sa_len;
-
- if (!(sa = resolve_server(server, &sa_len))) {
- c->error = PA_ERROR_INVALIDSERVER;
- return -1;
- }
-
- c->client = pa_socket_client_new_sockaddr(c->mainloop, sa, sa_len);
- pa_xfree(sa);
-
- if (!c->client) {
- c->error = PA_ERROR_CONNECTIONREFUSED;
- return -1;
- }
- }
-
- c->connect_complete_callback = complete;
- c->connect_complete_userdata = userdata;
-
- pa_socket_client_set_callback(c->client, on_connection, c);
- c->state = CONTEXT_CONNECTING;
-
- return 0;
-}
-
-int pa_context_is_dead(struct pa_context *c) {
- assert(c);
- return c->state == CONTEXT_DEAD;
-}
-
-int pa_context_is_ready(struct pa_context *c) {
- assert(c);
- return c->state == CONTEXT_READY;
-}
-
-int pa_context_errno(struct pa_context *c) {
- assert(c);
- return c->error;
-}
-
-void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata) {
- assert(c);
- c->die_callback = cb;
- c->die_userdata = userdata;
-}
-
-static void command_playback_stream_killed(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_stream *s;
- uint32_t channel;
- assert(pd && (command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED) && t && c);
-
- if (pa_tagstruct_getu32(t, &channel) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel)))
- return;
-
- c->error = PA_ERROR_KILLED;
- stream_dead(s);
-}
-
-static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s;
- struct pa_context *c = userdata;
- uint32_t bytes, channel;
- assert(pd && command == PA_COMMAND_REQUEST && t && c);
-
- if (pa_tagstruct_getu32(t, &channel) < 0 ||
- pa_tagstruct_getu32(t, &bytes) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (!(s = pa_dynarray_get(c->playback_streams, channel)))
- return;
-
- if (s->state != STREAM_READY)
- return;
-
- s->requested_bytes += bytes;
-
- if (s->requested_bytes && s->write_callback)
- s->write_callback(s, s->requested_bytes, s->write_userdata);
-}
-
-static void create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s && s->state == STREAM_CREATING);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- stream_dead(s);
- if (s->create_complete_callback)
- s->create_complete_callback(s, 0, s->create_complete_userdata);
-
- return;
- }
-
- if (pa_tagstruct_getu32(t, &s->channel) < 0 ||
- ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) ||
- !pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- s->channel_valid = 1;
- pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s);
-
- s->state = STREAM_READY;
- if (s->create_complete_callback)
- s->create_complete_callback(s, 1, s->create_complete_userdata);
-}
-
-static void create_stream(struct pa_stream *s, const char *dev) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(s);
-
- s->state = STREAM_CREATING;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM);
- pa_tagstruct_putu32(t, tag = s->context->ctag++);
- pa_tagstruct_puts(t, s->name);
- pa_tagstruct_put_sample_spec(t, &s->sample_spec);
- pa_tagstruct_putu32(t, (uint32_t) -1);
- pa_tagstruct_puts(t, dev ? dev : "");
- pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
- if (s->direction == PA_STREAM_PLAYBACK) {
- pa_tagstruct_putu32(t, s->buffer_attr.tlength);
- pa_tagstruct_putu32(t, s->buffer_attr.prebuf);
- pa_tagstruct_putu32(t, s->buffer_attr.minreq);
- } else
- pa_tagstruct_putu32(t, s->buffer_attr.fragsize);
-
- pa_pstream_send_tagstruct(s->context->pstream, t);
- pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s);
-}
-
-static struct pa_stream *internal_stream_new(struct pa_context *c) {
- struct pa_stream *s;
-
- s = pa_xmalloc(sizeof(struct pa_stream));
- s->context = c;
-
- s->read_callback = NULL;
- s->read_userdata = NULL;
- s->write_callback = NULL;
- s->write_userdata = NULL;
- s->die_callback = NULL;
- s->die_userdata = NULL;
- s->create_complete_callback = NULL;
- s->create_complete_userdata = NULL;
- s->get_latency_callback = NULL;
- s->get_latency_userdata = NULL;
- s->finish_sample_callback = NULL;
- s->finish_sample_userdata = NULL;
-
- s->name = NULL;
- s->state = STREAM_CREATING;
- s->requested_bytes = 0;
- s->channel = 0;
- s->channel_valid = 0;
- s->device_index = (uint32_t) -1;
-
- memset(&s->buffer_attr, 0, sizeof(s->buffer_attr));
-
- s->next = c->first_stream;
- if (s->next)
- s->next->previous = s;
- s->previous = NULL;
- c->first_stream = s;
-
- return s;
-}
-
-struct pa_stream* pa_stream_new(
- struct pa_context *c,
- enum pa_stream_direction dir,
- const char *dev,
- const char *name,
- const struct pa_sample_spec *ss,
- const struct pa_buffer_attr *attr,
- void (*complete) (struct pa_stream*s, int success, void *userdata),
- void *userdata) {
-
- struct pa_stream *s;
-
- assert(c && name && ss && c->state == CONTEXT_READY && (dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD));
-
- s = internal_stream_new(c);
- assert(s);
-
- s->create_complete_callback = complete;
- s->create_complete_userdata = userdata;
- s->name = pa_xstrdup(name);
- s->state = STREAM_CREATING;
- s->direction = dir;
- s->sample_spec = *ss;
- if (attr)
- s->buffer_attr = *attr;
- else {
- s->buffer_attr.maxlength = DEFAULT_MAXLENGTH;
- s->buffer_attr.tlength = DEFAULT_TLENGTH;
- s->buffer_attr.prebuf = DEFAULT_PREBUF;
- s->buffer_attr.minreq = DEFAULT_MINREQ;
- s->buffer_attr.fragsize = DEFAULT_FRAGSIZE;
- }
-
- create_stream(s, dev);
-
- return s;
-}
-
-void pa_stream_free(struct pa_stream *s) {
- assert(s && s->context);
-
- if (s->context->pdispatch)
- pa_pdispatch_unregister_reply(s->context->pdispatch, s);
-
- pa_xfree(s->name);
-
- if (s->channel_valid && s->context->state == CONTEXT_READY) {
- struct pa_tagstruct *t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_DELETE_PLAYBACK_STREAM :
- (s->direction == PA_STREAM_RECORD ? PA_COMMAND_DELETE_RECORD_STREAM : PA_COMMAND_DELETE_UPLOAD_STREAM));
- pa_tagstruct_putu32(t, s->context->ctag++);
- pa_tagstruct_putu32(t, s->channel);
- pa_pstream_send_tagstruct(s->context->pstream, t);
- }
-
- if (s->channel_valid)
- pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL);
-
- if (s->next)
- s->next->previous = s->previous;
- if (s->previous)
- s->previous->next = s->next;
- else
- s->context->first_stream = s->next;
-
- pa_xfree(s);
-}
-
-void pa_stream_set_write_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata) {
- s->write_callback = cb;
- s->write_userdata = userdata;
-}
-
-void pa_stream_write(struct pa_stream *s, const void *data, size_t length) {
- struct pa_memchunk chunk;
- assert(s && s->context && data && length && s->state == STREAM_READY);
-
- chunk.memblock = pa_memblock_new(length);
- assert(chunk.memblock && chunk.memblock->data);
- memcpy(chunk.memblock->data, data, length);
- chunk.index = 0;
- chunk.length = length;
-
- pa_pstream_send_memblock(s->context->pstream, s->channel, 0, &chunk);
- pa_memblock_unref(chunk.memblock);
-
- /*fprintf(stderr, "Sent %u bytes\n", length);*/
-
- if (length < s->requested_bytes)
- s->requested_bytes -= length;
- else
- s->requested_bytes = 0;
-}
-
-size_t pa_stream_writable_size(struct pa_stream *s) {
- assert(s && s->state == STREAM_READY);
- return s->requested_bytes;
-}
-
-void pa_stream_set_read_callback(struct pa_stream *s, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata) {
- assert(s && cb);
- s->read_callback = cb;
- s->read_userdata = userdata;
-}
-
-int pa_stream_is_dead(struct pa_stream *s) {
- return s->state == STREAM_DEAD;
-}
-
-int pa_stream_is_ready(struct pa_stream*s) {
- return s->state == STREAM_READY;
-}
-
-void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata) {
- assert(s);
- s->die_callback = cb;
- s->die_userdata = userdata;
-}
-
-int pa_context_is_pending(struct pa_context *c) {
- assert(c);
-
- if (c->state != CONTEXT_READY)
- return 0;
-
- return pa_pstream_is_pending(c->pstream) || pa_pdispatch_is_pending(c->pdispatch);
-}
-
-struct pa_context* pa_stream_get_context(struct pa_stream *p) {
- assert(p);
- return p->context;
-}
-
-static void set_dispatch_callbacks(struct pa_context *c);
-
-static void pdispatch_drain_callback(struct pa_pdispatch*pd, void *userdata) {
- set_dispatch_callbacks(userdata);
-}
-
-static void pstream_drain_callback(struct pa_pstream *s, void *userdata) {
- set_dispatch_callbacks(userdata);
-}
-
-static void set_dispatch_callbacks(struct pa_context *c) {
- assert(c && c->state == CONTEXT_READY);
-
- pa_pstream_set_drain_callback(c->pstream, NULL, NULL);
- pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL);
-
- if (pa_pdispatch_is_pending(c->pdispatch)) {
- pa_pdispatch_set_drain_callback(c->pdispatch, pdispatch_drain_callback, c);
- return;
- }
-
- if (pa_pstream_is_pending(c->pstream)) {
- pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c);
- return;
- }
-
- assert(c->drain_complete_callback);
- c->drain_complete_callback(c, c->drain_complete_userdata);
-}
-
-int pa_context_drain(
- struct pa_context *c,
- void (*complete) (struct pa_context*c, void *userdata),
- void *userdata) {
-
- assert(c && c->state == CONTEXT_READY);
-
- if (complete == NULL) {
- c->drain_complete_callback = NULL;
- pa_pstream_set_drain_callback(c->pstream, NULL, NULL);
- pa_pdispatch_set_drain_callback(c->pdispatch, NULL, NULL);
- return 0;
- }
-
- if (!pa_context_is_pending(c))
- return -1;
-
- c->drain_complete_callback = complete;
- c->drain_complete_userdata = userdata;
-
- set_dispatch_callbacks(c);
-
- return 0;
-}
-
-static void stream_drain_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- stream_dead(s);
- return;
- }
-
- if (s->state != STREAM_READY)
- return;
-
- if (!pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->drain_complete_callback) {
- void (*temp) (struct pa_stream*s, void *userdata) = s->drain_complete_callback;
- s->drain_complete_callback = NULL;
- temp(s, s->drain_complete_userdata);
- }
-}
-
-
-void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(s && s->state == STREAM_READY);
-
- if (!complete) {
- s->drain_complete_callback = NULL;
- return;
- }
-
- s->drain_complete_callback = complete;
- s->drain_complete_userdata = userdata;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
-
- pa_tagstruct_putu32(t, PA_COMMAND_DRAIN_PLAYBACK_STREAM);
- pa_tagstruct_putu32(t, tag = s->context->ctag++);
- pa_tagstruct_putu32(t, s->channel);
- pa_pstream_send_tagstruct(s->context->pstream, t);
- pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_drain_callback, s);
-}
-
-void pa_context_exit(struct pa_context *c) {
- struct pa_tagstruct *t;
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_EXIT);
- pa_tagstruct_putu32(t, c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
-}
-
-static void context_stat_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- uint32_t total, count;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->stat_callback)
- c->stat_callback(c, (uint32_t) -1, (uint32_t) -1, c->stat_userdata);
- return;
- }
-
- if (pa_tagstruct_getu32(t, &count) < 0 ||
- pa_tagstruct_getu32(t, &total) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->stat_callback)
- c->stat_callback(c, count, total, c->stat_userdata);
-}
-
-void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata) {
- uint32_t tag;
- struct pa_tagstruct *t;
-
- c->stat_callback = cb;
- c->stat_userdata = userdata;
-
- if (cb == NULL)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_STAT);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_stat_callback, c);
-}
-
-static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- uint32_t latency;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- if (s->get_latency_callback)
- s->get_latency_callback(s, (uint32_t) -1, s->get_latency_userdata);
- return;
- }
-
- if (pa_tagstruct_getu32(t, &latency) < 0 ||
- !pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->get_latency_callback)
- s->get_latency_callback(s, latency, s->get_latency_userdata);
-}
-
-void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata) {
- uint32_t tag;
- struct pa_tagstruct *t;
-
- p->get_latency_callback = cb;
- p->get_latency_userdata = userdata;
-
- if (cb == NULL)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY);
- pa_tagstruct_putu32(t, tag = p->context->ctag++);
- pa_tagstruct_putu32(t, p->channel);
- pa_pstream_send_tagstruct(p->context->pstream, t);
- pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, p);
-}
-
-struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata) {
- struct pa_stream *s;
- struct pa_tagstruct *t;
- uint32_t tag;
-
- s = internal_stream_new(c);
- assert(s);
-
- s->create_complete_callback = cb;
- s->create_complete_userdata = userdata;
- s->name = pa_xstrdup(name);
- s->state = STREAM_CREATING;
- s->direction = PA_STREAM_UPLOAD;
- s->sample_spec = *ss;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_CREATE_UPLOAD_STREAM);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, name);
- pa_tagstruct_put_sample_spec(t, ss);
- pa_tagstruct_putu32(t, length);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, s);
-
- return s;
-}
-
-static void stream_finish_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_stream *s = userdata;
- assert(pd && s);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(s->context, command, t) < 0) {
- context_dead(s->context);
- return;
- }
-
- if (s->finish_sample_callback)
- s->finish_sample_callback(s, 0, s->finish_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- s->context->error = PA_ERROR_PROTOCOL;
- context_dead(s->context);
- return;
- }
-
- if (s->finish_sample_callback)
- s->finish_sample_callback(s, 1, s->finish_sample_userdata);
-}
-
-void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(p);
-
- p->finish_sample_callback = cb;
- p->finish_sample_userdata = userdata;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_FINISH_UPLOAD_STREAM);
- pa_tagstruct_putu32(t, tag = p->context->ctag++);
- pa_tagstruct_putu32(t, p->channel);
- pa_pstream_send_tagstruct(p->context->pstream, t);
- pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_finish_sample_callback, p);
-}
-
-static void context_play_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->play_sample_callback)
- c->play_sample_callback(c, 0, c->play_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->play_sample_callback)
- c->play_sample_callback(c, 1, c->play_sample_userdata);
-}
-
-void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c && name && *name && (!dev || *dev));
-
- c->play_sample_callback = cb;
- c->play_sample_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_PLAY_SAMPLE);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, (uint32_t) -1);
- pa_tagstruct_puts(t, dev ? dev : "");
- pa_tagstruct_putu32(t, volume);
- pa_tagstruct_puts(t, name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_play_sample_callback, c);
-}
-
-static void context_remove_sample_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->remove_sample_callback)
- c->remove_sample_callback(c, 0, c->remove_sample_userdata);
- return;
- }
-
- if (!pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->remove_sample_callback)
- c->remove_sample_callback(c, 1, c->remove_sample_userdata);
-}
-
-void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c && name);
-
- c->remove_sample_callback = cb;
- c->remove_sample_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_REMOVE_SAMPLE);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_puts(t, name);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_remove_sample_callback, c);
-}
-
-static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- struct pa_server_info i;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_server_info_callback)
- c->get_server_info_callback(c, NULL, c->get_server_info_userdata);
- return;
- }
-
- if (pa_tagstruct_gets(t, &i.server_name) < 0 ||
- pa_tagstruct_gets(t, &i.server_version) < 0 ||
- pa_tagstruct_gets(t, &i.user_name) < 0 ||
- pa_tagstruct_gets(t, &i.host_name) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_server_info_callback)
- c->get_server_info_callback(c, &i, c->get_server_info_userdata);
-}
-
-void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_server_info_callback = cb;
- c->get_server_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SERVER_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_server_info_callback, c);
-}
-
-static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, NULL, 0, c->get_sink_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_sink_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.description) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
- pa_tagstruct_getu32(t, &i.volume) < 0 ||
- pa_tagstruct_getu32(t, &i.monitor_source) < 0 ||
- pa_tagstruct_gets(t, &i.monitor_source_name) < 0 ||
- pa_tagstruct_getu32(t, &i.latency) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, &i, 0, c->get_sink_info_userdata);
- }
-
- if (c->get_sink_info_callback)
- c->get_sink_info_callback(c, NULL, 1, c->get_sink_info_userdata);
-}
-
-void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_sink_info_callback = cb;
- c->get_sink_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c);
-}
-
-static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, NULL, 0, c->get_source_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_source_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.description) < 0 ||
- pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
- pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 ||
- pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, &i, 0, c->get_source_info_userdata);
- }
-
- if (c->get_source_info_callback)
- c->get_source_info_callback(c, NULL, 1, c->get_source_info_userdata);
-}
-
-void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_source_info_callback = cb;
- c->get_source_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c);
-}
-
-void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- assert(c);
-
- c->subscribe_callback = cb;
- c->subscribe_userdata = userdata;
- c->subscribe_mask = m;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE);
- pa_tagstruct_putu32(t, c->ctag++);
- pa_tagstruct_putu32(t, cb ? m : 0);
- pa_pstream_send_tagstruct(c->pstream, t);
-}
-
-static void command_subscribe_event(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- enum pa_subscription_event_type e;
- uint32_t index;
- assert(pd && command == PA_COMMAND_SUBSCRIBE_EVENT && t && c);
-
- if (pa_tagstruct_getu32(t, &e) < 0 ||
- pa_tagstruct_getu32(t, &index) < 0 ||
- !pa_tagstruct_eof(t)) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (pa_subscription_match_flags(c->subscribe_mask, e) && c->subscribe_callback)
- c->subscribe_callback(c, e, index, c->subscribe_userdata);
-}
-
-void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_sink_info_callback = cb;
- c->get_sink_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SINK_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_tagstruct_puts(t, "");
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sink_info_callback, c);
-}
-
-void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_source_info_callback = cb;
- c->get_source_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_SOURCE_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_tagstruct_puts(t, "");
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c);
-}
-
-static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, NULL, 0, c->get_client_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_client_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.protocol_name) < 0 ||
- pa_tagstruct_getu32(t, &i.owner_module) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, &i, 0, c->get_client_info_userdata);
- }
-
- if (c->get_client_info_callback)
- c->get_client_info_callback(c, NULL, 1, c->get_client_info_userdata);
-}
-
-
-void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_client_info_callback = cb;
- c->get_client_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c);
-}
-
-void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_client_info_callback = cb;
- c->get_client_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c);
-}
-
-static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
- struct pa_context *c = userdata;
- assert(pd && c);
-
- if (command != PA_COMMAND_REPLY) {
- if (handle_error(c, command, t) < 0) {
- context_dead(c);
- return;
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, NULL, 0, c->get_module_info_userdata);
- return;
- }
-
- while (!pa_tagstruct_eof(t)) {
- struct pa_module_info i;
-
- if (pa_tagstruct_getu32(t, &i.index) < 0 ||
- pa_tagstruct_gets(t, &i.name) < 0 ||
- pa_tagstruct_gets(t, &i.argument) < 0 ||
- pa_tagstruct_getu32(t, &i.n_used) < 0 ||
- pa_tagstruct_getu32(t, &i.auto_unload) < 0) {
- c->error = PA_ERROR_PROTOCOL;
- context_dead(c);
- return;
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, &i, 0, c->get_module_info_userdata);
- }
-
- if (c->get_module_info_callback)
- c->get_module_info_callback(c, NULL, 1, c->get_module_info_userdata);
-}
-
-void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_module_info_callback = cb;
- c->get_module_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_tagstruct_putu32(t, index);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c);
-}
-
-void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) {
- struct pa_tagstruct *t;
- uint32_t tag;
- assert(c);
-
- c->get_module_info_callback = cb;
- c->get_module_info_userdata = userdata;
-
- if (!cb)
- return;
-
- t = pa_tagstruct_new(NULL, 0);
- assert(t);
- pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO_LIST);
- pa_tagstruct_putu32(t, tag = c->ctag++);
- pa_pstream_send_tagstruct(c->pstream, t);
- pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c);
-}
diff --git a/polyp/polyplib.h b/polyp/polyplib.h
index a0dd9f9c..b9e5637c 100644
--- a/polyp/polyplib.h
+++ b/polyp/polyplib.h
@@ -22,157 +22,13 @@
USA.
***/
-#include <sys/types.h>
-
+#include "mainloop-api.h"
#include "sample.h"
#include "polyplib-def.h"
-#include "mainloop-api.h"
-
-#ifdef __cplusplus
-//extern "C" {
-#endif
-
-struct pa_context;
-struct pa_stream;
-
-struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char *name);
-void pa_context_unref(struct pa_context *c);
-struct pa_context* pa_context_ref(struct pa_context *c);
-
-int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata);
-int pa_context_drain(struct pa_context *c, void (*complete) (struct pa_context*c, void *userdata), void *userdata);
-void pa_context_set_die_callback(struct pa_context *c, void (*cb)(struct pa_context *c, void *userdata), void *userdata);
-
-int pa_context_is_dead(struct pa_context *c);
-int pa_context_is_ready(struct pa_context *c);
-int pa_context_errno(struct pa_context *c);
-
-int pa_context_is_pending(struct pa_context *c);
-
-struct pa_stream* pa_stream_new(struct pa_context *c, enum pa_stream_direction dir, const char *dev, const char *name, const struct pa_sample_spec *ss, const struct pa_buffer_attr *attr, void (*complete) (struct pa_stream*s, int success, void *userdata), void *userdata);
-void pa_stream_unref(struct pa_stream *s);
-struct pa_stream *pa_stream_ref(struct pa_stream *s);
-
-void pa_stream_drain(struct pa_stream *s, void (*complete) (struct pa_stream*s, void *userdata), void *userdata);
-
-void pa_stream_set_die_callback(struct pa_stream *s, void (*cb)(struct pa_stream *s, void *userdata), void *userdata);
-
-void pa_stream_set_write_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, size_t length, void *userdata), void *userdata);
-void pa_stream_write(struct pa_stream *p, const void *data, size_t length);
-size_t pa_stream_writable_size(struct pa_stream *p);
-
-void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_stream *p, const void*data, size_t length, void *userdata), void *userdata);
-
-int pa_stream_is_dead(struct pa_stream *p);
-int pa_stream_is_ready(struct pa_stream*p);
-
-void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata);
-
-struct pa_context* pa_stream_get_context(struct pa_stream *p);
-
-uint32_t pa_stream_get_index(struct pa_stream *s);
-
-struct pa_stream* pa_context_upload_sample(struct pa_context *c, const char *name, const struct pa_sample_spec *ss, size_t length, void (*cb) (struct pa_stream*s, int success, void *userdata), void *userdata);
-void pa_stream_finish_sample(struct pa_stream *p, void (*cb)(struct pa_stream*s, int success, void *userdata), void *userdata);
-
-void pa_context_play_sample(struct pa_context *c, const char *name, const char *dev, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-void pa_context_remove_sample(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-
-struct pa_sink_info {
- const char *name;
- uint32_t index;
- const char *description;
- struct pa_sample_spec sample_spec;
- uint32_t owner_module;
- uint32_t volume;
- uint32_t monitor_source;
- const char *monitor_source_name;
- uint32_t latency;
-};
-
-void pa_context_get_sink_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata), void *userdata);
-
-struct pa_source_info {
- const char *name;
- uint32_t index;
- const char *description;
- struct pa_sample_spec sample_spec;
- uint32_t owner_module;
- uint32_t monitor_of_sink;
- const char *monitor_of_sink_name;
-};
-
-void pa_context_get_source_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t id, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata), void *userdata);
-
-struct pa_server_info {
- const char *user_name;
- const char *host_name;
- const char *server_version;
- const char *server_name;
- struct pa_sample_spec sample_spec;
-};
-
-void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata);
-
-struct pa_module_info {
- uint32_t index;
- const char*name, *argument;
- uint32_t n_used, auto_unload;
-};
-
-void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata);
-
-struct pa_client_info {
- uint32_t index;
- const char *name;
- uint32_t owner_module;
- const char *protocol_name;
-};
-
-void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata);
-
-struct pa_sink_input_info {
- uint32_t index;
- const char *name;
- uint32_t owner_module;
- uint32_t owner_client;
- uint32_t sink;
- struct pa_sample_spec sample_spec;
- uint32_t volume;
- uint32_t latency;
-};
-
-void pa_context_get_sink_input_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_sink_input_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sink_input_info*i, int is_last, void *userdata), void *userdata);
-
-struct pa_source_output_info {
- uint32_t index;
- const char *name;
- uint32_t owner_module;
- uint32_t owner_client;
- uint32_t source;
- struct pa_sample_spec sample_spec;
-};
-
-void pa_context_get_source_output_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata);
-void pa_context_get_source_output_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_source_output_info*i, int is_last, void *userdata), void *userdata);
-
-void pa_context_set_sink_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-void pa_context_set_sink_input_volume(struct pa_context *c, uint32_t index, uint32_t volume, void (*cb)(struct pa_context *c, int success, void *userdata), void *userdata);
-
-void pa_context_exit(struct pa_context *c);
-void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint32_t count, uint32_t total, void *userdata), void *userdata);
-
-void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata);
-
-#ifdef __cplusplus
-}
-#endif
+#include "polyplib-context.h"
+#include "polyplib-stream.h"
+#include "polyplib-introspect.h"
+#include "polyplib-subscribe.h"
+#include "polyplib-scache.h"
#endif
diff --git a/polyp/sample-util.c b/polyp/sample-util.c
index 5b1cd626..8f5558a4 100644
--- a/polyp/sample-util.c
+++ b/polyp/sample-util.c
@@ -135,10 +135,3 @@ void pa_volume_memchunk(struct pa_memchunk*c, const struct pa_sample_spec *spec,
}
}
-uint32_t pa_volume_multiply(uint32_t a, uint32_t b) {
- uint64_t p = a;
- p *= b;
- p /= PA_VOLUME_NORM;
-
- return (uint32_t) p;
-}
diff --git a/polyp/sample-util.h b/polyp/sample-util.h
index 73101ab4..66f40a16 100644
--- a/polyp/sample-util.h
+++ b/polyp/sample-util.h
@@ -26,8 +26,6 @@
#include "memblock.h"
#include "memchunk.h"
-#define PA_VOLUME_NORM (0x100)
-#define PA_VOLUME_MUTE (0)
struct pa_memblock *pa_silence_memblock(struct pa_memblock* b, const struct pa_sample_spec *spec);
void pa_silence_memchunk(struct pa_memchunk *c, const struct pa_sample_spec *spec);
@@ -43,6 +41,4 @@ size_t pa_mix(struct pa_mix_info channels[], unsigned nchannels, void *data, siz
void pa_volume_memchunk(struct pa_memchunk*c, const struct pa_sample_spec *spec, uint32_t volume);
-uint32_t pa_volume_multiply(uint32_t a, uint32_t b);
-
#endif
diff --git a/polyp/sample.c b/polyp/sample.c
index e4c4bd52..4f93f2b7 100644
--- a/polyp/sample.c
+++ b/polyp/sample.c
@@ -96,3 +96,11 @@ void pa_sample_snprint(char *s, size_t l, const struct pa_sample_spec *spec) {
assert(pa_sample_spec_valid(spec));
snprintf(s, l, "%s %uch %uHz", table[spec->format], spec->channels, spec->rate);
}
+
+uint32_t pa_volume_multiply(uint32_t a, uint32_t b) {
+ uint64_t p = a;
+ p *= b;
+ p /= PA_VOLUME_NORM;
+
+ return (uint32_t) p;
+}
diff --git a/polyp/sample.h b/polyp/sample.h
index 25027879..a7cde093 100644
--- a/polyp/sample.h
+++ b/polyp/sample.h
@@ -25,9 +25,9 @@
#include <inttypes.h>
#include <sys/types.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
+#include "cdecl.h"
+
+PA_C_DECL_BEGIN
enum pa_sample_format {
PA_SAMPLE_U8,
@@ -49,10 +49,11 @@ enum pa_sample_format {
#endif
#define PA_SAMPLE_FLOAT32 PA_SAMPLE_FLOAT32NE
+/** A sample format and attribute specification */
struct pa_sample_spec {
- enum pa_sample_format format;
- uint32_t rate;
- uint8_t channels;
+ enum pa_sample_format format; /**< The sample format */
+ uint32_t rate; /**< The sample rate. (e.g. 44100) */
+ uint8_t channels; /**< Audio channels. (1 for mono, 2 for stereo, ...) */
};
size_t pa_bytes_per_second(const struct pa_sample_spec *spec);
@@ -64,8 +65,10 @@ int pa_sample_spec_equal(const struct pa_sample_spec*a, const struct pa_sample_s
#define PA_SAMPLE_SNPRINT_MAX_LENGTH 32
void pa_sample_snprint(char *s, size_t l, const struct pa_sample_spec *spec);
-#ifdef __cplusplus
-}
-#endif
+#define PA_VOLUME_NORM (0x100)
+#define PA_VOLUME_MUTE (0)
+uint32_t pa_volume_multiply(uint32_t a, uint32_t b);
+
+PA_C_DECL_END
#endif
diff --git a/polyp/socket-client.c b/polyp/socket-client.c
index e8cb2f92..dffbfe7d 100644
--- a/polyp/socket-client.c
+++ b/polyp/socket-client.c
@@ -120,7 +120,7 @@ static int do_connect(struct pa_socket_client *c, const struct sockaddr *sa, soc
if ((r = connect(c->fd, sa, len)) < 0) {
if (errno != EINPROGRESS) {
- fprintf(stderr, "connect(): %s\n", strerror(errno));
+ /*fprintf(stderr, "connect(): %s\n", strerror(errno));*/
return -1;
}
diff --git a/polyp/socket-client.h b/polyp/socket-client.h
index 2a89210e..7b9e2a72 100644
--- a/polyp/socket-client.h
+++ b/polyp/socket-client.h
@@ -23,6 +23,8 @@
***/
#include <inttypes.h>
+#include <sys/socket.h>
+
#include "mainloop-api.h"
#include "iochannel.h"
diff --git a/polyp/tagstruct.h b/polyp/tagstruct.h
index aefd03c4..bcd7f456 100644
--- a/polyp/tagstruct.h
+++ b/polyp/tagstruct.h
@@ -48,6 +48,4 @@ int pa_tagstruct_get_arbitrary(struct pa_tagstruct *t, const void **p, size_t le
int pa_tagstruct_eof(struct pa_tagstruct*t);
const uint8_t* pa_tagstruct_data(struct pa_tagstruct*t, size_t *l);
-
-
#endif
diff --git a/polyp/xmalloc.c b/polyp/xmalloc.c
index 8ff3054d..7d8b4821 100644
--- a/polyp/xmalloc.c
+++ b/polyp/xmalloc.c
@@ -52,25 +52,36 @@ void *pa_xrealloc(void *ptr, size_t size) {
return p;
}
-char *pa_xstrdup(const char *s) {
- if (!s)
+void* pa_xmemdup(const void *p, size_t l) {
+ if (!p)
return NULL;
else {
- char *r = strdup(s);
- if (!r)
- oom();
-
+ char *r = pa_xmalloc(l);
+ memcpy(r, p, l);
return r;
}
}
+char *pa_xstrdup(const char *s) {
+ if (!s)
+ return NULL;
+
+ return pa_xmemdup(s, strlen(s)+1);
+}
+
char *pa_xstrndup(const char *s, size_t l) {
if (!s)
return NULL;
else {
- char *r = strndup(s, l);
- if (!r)
- oom();
+ char *r;
+ size_t t = strlen(s);
+
+ if (t > l)
+ t = l;
+
+ r = pa_xmemdup(s, t+1);
+ r[t] = 0;
return r;
}
}
+
diff --git a/polyp/xmalloc.h b/polyp/xmalloc.h
index 45209b05..eaf8f708 100644
--- a/polyp/xmalloc.h
+++ b/polyp/xmalloc.h
@@ -12,4 +12,6 @@ void *pa_xrealloc(void *ptr, size_t size);
char *pa_xstrdup(const char *s);
char *pa_xstrndup(const char *s, size_t l);
+void* pa_xmemdup(const void *p, size_t l);
+
#endif