summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2004-08-19 23:14:59 +0000
committerLennart Poettering <lennart@poettering.net>2004-08-19 23:14:59 +0000
commitf9b58fb0eafdc332e500a0851b0506146c2b14cd (patch)
tree3f4b197fdd9e21af7ad404de9dff61ed845a4154
parente0fe68a2d4e967c2b3d7afd300c854d173dcd95b (diff)
move sample cache to namereg
documentation git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@141 fefdeb5f-60dc-0310-8127-8f9354f1896f
-rw-r--r--configure.ac2
-rw-r--r--doc/README.html.in41
-rw-r--r--polyp/cli-text.c8
-rw-r--r--polyp/core.c9
-rw-r--r--polyp/core.h4
-rw-r--r--polyp/glib-mainloop.c28
-rw-r--r--polyp/llist.h2
-rw-r--r--polyp/mainloop-api.h2
-rw-r--r--polyp/mainloop.c37
-rw-r--r--polyp/memblockq.c2
-rw-r--r--polyp/memchunk.c2
-rw-r--r--polyp/module-oss-mmap.c2
-rw-r--r--polyp/module-oss.c2
-rw-r--r--polyp/namereg.c9
-rw-r--r--polyp/namereg.h3
-rw-r--r--polyp/polyplib-def.h8
-rw-r--r--polyp/polyplib-introspect.c89
-rw-r--r--polyp/polyplib-introspect.h12
-rw-r--r--polyp/polyplib-operation.h1
-rw-r--r--polyp/polyplib-stream.c2
-rw-r--r--polyp/protocol-esound.c4
-rw-r--r--polyp/protocol-native.c45
-rw-r--r--polyp/sample.c2
-rw-r--r--polyp/scache.c66
-rw-r--r--polyp/scache.h2
-rw-r--r--polyp/strbuf.c2
-rw-r--r--polyp/strbuf.h2
27 files changed, 252 insertions, 136 deletions
diff --git a/configure.ac b/configure.ac
index a8c45269..96b4cf3a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -87,7 +87,7 @@ AC_SUBST(GLIB20_LIBS)
# If using GCC specifiy some additional parameters
if test "x$GCC" = "xyes" ; then
- CFLAGS="$CFLAGS -pipe -Wall -W -Wno-unused-parameter"
+ CFLAGS="$CFLAGS -pipe -W -Wall -Wno-unused-parameter -pedantic -std=c99"
fi
# LYNX documentation generation
diff --git a/doc/README.html.in b/doc/README.html.in
index 296d4506..4972c194 100644
--- a/doc/README.html.in
+++ b/doc/README.html.in
@@ -42,6 +42,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.</p>
<h2><a name="news">News</a></h2>
+<div class="news-date">Fri Aug 20 2004: </div> <p class="news-text"><a
+href="@PACKAGE_URL@polypaudio-0.2.tar.gz">Version 0.2</a> released;
+changes include: added sample cache, introspection API, client API
+documentation, module autoloading, glib support, a module for intercepting X11 bell events, and much more.</p>
<div class="news-date">Sat Jul 17 2004: </div> <p class="news-text"><a
href="@PACKAGE_URL@polypaudio-0.1.tar.gz">Version 0.1</a> released</p>
@@ -56,7 +60,7 @@ Daemon</a> (ESOUND). In addition to the features ESOUND provides
<tt>polypaudio</tt> has:</p>
<ul>
- <li>Extensible plugin architecture (<tt>dlopen()</tt>)</li>
+ <li>Extensible plugin architecture (by loading dynamic loadable modules with <tt>dlopen()</tt>)</li>
<li>Support for more than one sink/source</li>
<li>Better low latency behaviour</li>
<li>Embedabble into other software (the core is available as C library)</li>
@@ -64,6 +68,7 @@ Daemon</a> (ESOUND). In addition to the features ESOUND provides
<li>Simple command line interface for reconfiguring the daemon while running</li>
<li>Flexible, implicit sample type conversion and resampling</li>
<li>"Zero-Copy" architecture</li>
+ <li>Module autoloading</li>
</ul>
<p>Both the core and the client API are completely asynchronous making
@@ -74,31 +79,27 @@ available through <tt>polyplib</tt> is quite difficult to use there is
a simplified synchronous API wrapper <tt>polyplib-simple</tt>
available. A simple main loop implementation is available as well.</p>
-<p><tt>polypaudio</tt> is the successor of my previous, ill-fated attempt to write a sound server <a href="http://asd.sf.net/">asd</a>.</p>
+<p><tt>polypaudio</tt> is the successor of my previous, ill-fated
+attempt to write a sound server <a
+href="http://asd.sf.net/">asd</a>.</p>
+
+<p>A GTK GUI manager application for polypaudio is the <a
+href="http://0pointer.de/projects/paman/">Polypaudio Manager</a>.</p>
<h2><a name="status">Status</a></h2>
-<p>Version @PACKAGE_VERSION@ is quite usable. <tt>polypaudio</tt> does
-not yet match all ESOUND features: currently a sample cache and
-automatic releasing of unused sound drivers are missing. Have a look
-on the more extensive <a
-href="http://0pointer.de/cgi-bin/viewcvs.cgi/trunk/doc/todo?view=markup">TODO
-list</a>.</p>
+<p>Version @PACKAGE_VERSION@ is quite usable. It matches and supersedes ESOUND's feature set in nearly all areas.</p>
<h2><a name="documentation">Documentation</a></h2>
-<p>There is some prelimenary documentation available: <a
+<p>There is some preliminary documentation available: <a
href="modules.html"><tt>modules.html</tt></a>, <a
href="cli.html"><tt>cli.html</tt></a>, <a
-href="daemon.html"><tt>daemeon.html</tt></a>.</p>
+href="daemon.html"><tt>daemon.html</tt></a>.</p>
-<p>Documentation for developing with <tt>polypaudio</tt> is not yet
-available. Read the source, Luke! There are some example application
-available: for the <a
-href="http://0pointer.de/cgi-bin/viewcvs.cgi/trunk/polyp/pacat.c?view=markup">asynchronous
-API</a> and for the <a
-href="http://0pointer.de/cgi-bin/viewcvs.cgi/trunk/polyp/pacat-simple.c?view=markup">simple,
-synchronous API</a>.</p>
+<p>You may browser the <a href="http://www.doxygen.org/">Doxygen</a> generated <a
+href="http://0pointer.de/lennart/projects/polypaudio/doxygen/">programing
+documentation</a> for the client API. (Run <tt>make doxygen</tt> to generate this documentation from the source tree)</p>
<h3>First Steps</h3>
@@ -131,7 +132,9 @@ GNU libtool for source code configuration and shared library
management.</p>
<p><tt>polypaudio</tt> needs <a
-href="http://www.mega-nerd.com/SRC/">Secret Rabbit Code (aka <tt>libsamplerate</tt>)</a> and <a href="http://www.alsa-project.org/">alsa-lib</a>.</p>
+href="http://www.mega-nerd.com/SRC/">Secret Rabbit Code (aka
+<tt>libsamplerate</tt>)</a>, <a href="http://www.mega-nerd.com/SND"><tt>libsndfile</tt></a> and <a
+href="http://www.alsa-project.org/">alsa-lib</a>.</p>
<h2><a name="installation">Installation</a></h2>
@@ -156,7 +159,7 @@ compilation and <tt>make install</tt> (as root) for installation of
<p>If you want to be notified whenever I release a new version of this software use the subscription feature of <a href="http://freshmeat.net/projects/polypaudio/">Freshmeat</a>.</p>
<hr/>
-<address class="grey">Lennart Poettering &lt;@PACKAGE_BUGREPORT@&gt;, July 2004</address>
+<address class="grey">Lennart Poettering &lt;@PACKAGE_BUGREPORT@&gt;, August 2004</address>
<div class="grey"><i>$Id$</i></div>
</body>
diff --git a/polyp/cli-text.c b/polyp/cli-text.c
index 000d6d34..fa1ccdf9 100644
--- a/polyp/cli-text.c
+++ b/polyp/cli-text.c
@@ -212,13 +212,13 @@ char *pa_scache_list_to_string(struct pa_core *c) {
s = pa_strbuf_new();
assert(s);
- pa_strbuf_printf(s, "%u cache entries available.\n", c->scache_hashmap ? pa_hashmap_ncontents(c->scache_hashmap) : 0);
+ pa_strbuf_printf(s, "%u cache entries available.\n", c->scache ? pa_idxset_ncontents(c->scache) : 0);
- if (c->scache_hashmap) {
+ if (c->scache) {
struct pa_scache_entry *e;
- void *state = NULL;
+ uint32_t index = PA_IDXSET_INVALID;
- while ((e = pa_hashmap_iterate(c->scache_hashmap, &state))) {
+ for (e = pa_idxset_first(c->scache, &index); e; e = pa_idxset_next(c->scache, &index)) {
double l;
char ss[PA_SAMPLE_SNPRINT_MAX_LENGTH];
pa_sample_spec_snprint(ss, sizeof(ss), &e->sample_spec);
diff --git a/polyp/core.c b/polyp/core.c
index b43eb639..908564c1 100644
--- a/polyp/core.c
+++ b/polyp/core.c
@@ -53,8 +53,7 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) {
c->modules = NULL;
c->namereg = NULL;
- c->scache_idxset = NULL;
- c->scache_hashmap = NULL;
+ c->scache = NULL;
c->autoload_hashmap = NULL;
@@ -74,7 +73,7 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) {
pa_check_for_sigpipe();
return c;
-};
+}
void pa_core_free(struct pa_core *c) {
assert(c);
@@ -97,8 +96,8 @@ void pa_core_free(struct pa_core *c) {
assert(pa_idxset_isempty(c->sink_inputs));
pa_idxset_free(c->sink_inputs, NULL, NULL);
- pa_namereg_free(c);
pa_scache_free(c);
+ pa_namereg_free(c);
pa_autoload_free(c);
pa_subscription_free_all(c);
@@ -108,5 +107,5 @@ void pa_core_free(struct pa_core *c) {
pa_memblock_stat_unref(c->memblock_stat);
pa_xfree(c);
-};
+}
diff --git a/polyp/core.h b/polyp/core.h
index c0a2d6d8..a297d4e0 100644
--- a/polyp/core.h
+++ b/polyp/core.h
@@ -31,9 +31,9 @@
struct pa_core {
struct pa_mainloop_api *mainloop;
- struct pa_idxset *clients, *sinks, *sources, *sink_inputs, *source_outputs, *modules, *scache_idxset;
+ struct pa_idxset *clients, *sinks, *sources, *sink_inputs, *source_outputs, *modules, *scache;
- struct pa_hashmap *namereg, *scache_hashmap, *autoload_hashmap;
+ struct pa_hashmap *namereg, *autoload_hashmap;
char *default_source_name, *default_sink_name;
diff --git a/polyp/glib-mainloop.c b/polyp/glib-mainloop.c
index a91f48ec..4fee0a4a 100644
--- a/polyp/glib-mainloop.c
+++ b/polyp/glib-mainloop.c
@@ -384,24 +384,24 @@ static void glib_quit(struct pa_mainloop_api*a, int retval) {
}
static const struct pa_mainloop_api vtable = {
- userdata: NULL,
+ .userdata = NULL,
- io_new: glib_io_new,
- io_enable: glib_io_enable,
- io_free: glib_io_free,
- io_set_destroy: glib_io_set_destroy,
+ .io_new = glib_io_new,
+ .io_enable = glib_io_enable,
+ .io_free = glib_io_free,
+ .io_set_destroy= glib_io_set_destroy,
- time_new : glib_time_new,
- time_restart : glib_time_restart,
- time_free : glib_time_free,
- time_set_destroy : glib_time_set_destroy,
+ .time_new = glib_time_new,
+ .time_restart = glib_time_restart,
+ .time_free = glib_time_free,
+ .time_set_destroy = glib_time_set_destroy,
- defer_new : glib_defer_new,
- defer_enable : glib_defer_enable,
- defer_free : glib_defer_free,
- defer_set_destroy : glib_defer_set_destroy,
+ .defer_new = glib_defer_new,
+ .defer_enable = glib_defer_enable,
+ .defer_free = glib_defer_free,
+ .defer_set_destroy = glib_defer_set_destroy,
- quit : glib_quit,
+ .quit = glib_quit,
};
struct pa_glib_mainloop *pa_glib_mainloop_new(GMainContext *c) {
diff --git a/polyp/llist.h b/polyp/llist.h
index 12a33e90..ec8e0299 100644
--- a/polyp/llist.h
+++ b/polyp/llist.h
@@ -24,7 +24,7 @@
#define PA_LLIST_HEAD(t,name) t *name
-#define PA_LLIST_FIELDS(t) t *next, *prev;
+#define PA_LLIST_FIELDS(t) t *next, *prev
#define PA_LLIST_HEAD_INIT(t,item) do { (item) = NULL; } while(0)
diff --git a/polyp/mainloop-api.h b/polyp/mainloop-api.h
index e631c7ac..43d150e4 100644
--- a/polyp/mainloop-api.h
+++ b/polyp/mainloop-api.h
@@ -50,7 +50,7 @@ enum pa_io_event_flags {
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 */
+ PA_IO_EVENT_ERROR = 8 /**< Error event */
};
/** \struct pa_io_event
diff --git a/polyp/mainloop.c b/polyp/mainloop.c
index c678537e..84505bb6 100644
--- a/polyp/mainloop.c
+++ b/polyp/mainloop.c
@@ -38,9 +38,6 @@
#include "idxset.h"
#include "xmalloc.h"
-struct pa_base_event {
-};
-
struct pa_io_event {
struct pa_mainloop *mainloop;
int dead;
@@ -225,24 +222,24 @@ static void mainloop_quit(struct pa_mainloop_api*a, int retval) {
}
static const struct pa_mainloop_api vtable = {
- userdata: NULL,
+ .userdata = NULL,
- io_new: mainloop_io_new,
- io_enable: mainloop_io_enable,
- io_free: mainloop_io_free,
- io_set_destroy: mainloop_io_set_destroy,
+ .io_new= mainloop_io_new,
+ .io_enable= mainloop_io_enable,
+ .io_free= mainloop_io_free,
+ .io_set_destroy= mainloop_io_set_destroy,
- time_new : mainloop_time_new,
- time_restart : mainloop_time_restart,
- time_free : mainloop_time_free,
- time_set_destroy : mainloop_time_set_destroy,
+ .time_new = mainloop_time_new,
+ .time_restart = mainloop_time_restart,
+ .time_free = mainloop_time_free,
+ .time_set_destroy = mainloop_time_set_destroy,
- defer_new : mainloop_defer_new,
- defer_enable : mainloop_defer_enable,
- defer_free : mainloop_defer_free,
- defer_set_destroy : mainloop_defer_set_destroy,
+ .defer_new = mainloop_defer_new,
+ .defer_enable = mainloop_defer_enable,
+ .defer_free = mainloop_defer_free,
+ .defer_set_destroy = mainloop_defer_set_destroy,
- quit : mainloop_quit,
+ .quit = mainloop_quit,
};
struct pa_mainloop *pa_mainloop_new(void) {
@@ -282,7 +279,7 @@ static int io_foreach(void *p, uint32_t index, int *del, void*userdata) {
pa_xfree(e);
*del = 1;
return 0;
-};
+}
static int time_foreach(void *p, uint32_t index, int *del, void*userdata) {
struct pa_time_event *e = p;
@@ -297,7 +294,7 @@ static int time_foreach(void *p, uint32_t index, int *del, void*userdata) {
pa_xfree(e);
*del = 1;
return 0;
-};
+}
static int defer_foreach(void *p, uint32_t index, int *del, void*userdata) {
struct pa_defer_event *e = p;
@@ -312,7 +309,7 @@ static int defer_foreach(void *p, uint32_t index, int *del, void*userdata) {
pa_xfree(e);
*del = 1;
return 0;
-};
+}
void pa_mainloop_free(struct pa_mainloop* m) {
int all = 1;
diff --git a/polyp/memblockq.c b/polyp/memblockq.c
index bc5d7437..085c0510 100644
--- a/polyp/memblockq.c
+++ b/polyp/memblockq.c
@@ -189,9 +189,9 @@ int memblockq_pop(struct memblockq* bq, struct pa_memchunk *chunk) {
*/
static uint32_t age(struct timeval *tv) {
- assert(tv);
struct timeval now;
uint32_t r;
+ assert(tv);
if (tv->tv_sec == 0)
return 0;
diff --git a/polyp/memchunk.c b/polyp/memchunk.c
index 5913c6e3..920189e2 100644
--- a/polyp/memchunk.c
+++ b/polyp/memchunk.c
@@ -88,8 +88,8 @@ void pa_mcalign_push(struct pa_mcalign *m, const struct pa_memchunk *c) {
}
int pa_mcalign_pop(struct pa_mcalign *m, struct pa_memchunk *c) {
- assert(m && c && m->base > m->buffer_fill);
int ret;
+ assert(m && c && m->base > m->buffer_fill);
if (!m->chunk.memblock)
return -1;
diff --git a/polyp/module-oss-mmap.c b/polyp/module-oss-mmap.c
index 7c7750d1..05e06178 100644
--- a/polyp/module-oss-mmap.c
+++ b/polyp/module-oss-mmap.c
@@ -193,7 +193,7 @@ static void do_read(struct userdata *u) {
in_post_memblocks(u, info.blocks);
in_clear_memblocks(u, u->in_fragments/2);
-};
+}
static void io_callback(struct pa_mainloop_api *m, struct pa_io_event *e, int fd, enum pa_io_event_flags f, void *userdata) {
struct userdata *u = userdata;
diff --git a/polyp/module-oss.c b/polyp/module-oss.c
index d5517b5e..3fa3d1e3 100644
--- a/polyp/module-oss.c
+++ b/polyp/module-oss.c
@@ -146,7 +146,7 @@ static void do_read(struct userdata *u) {
pa_source_post(u->source, &memchunk);
pa_memblock_unref(memchunk.memblock);
-};
+}
static void io_callback(struct pa_iochannel *io, void*userdata) {
struct userdata *u = userdata;
diff --git a/polyp/namereg.c b/polyp/namereg.c
index b6a8c23f..72a4c648 100644
--- a/polyp/namereg.c
+++ b/polyp/namereg.c
@@ -134,8 +134,7 @@ void* pa_namereg_get(struct pa_core *c, const char *name, enum pa_namereg_type t
name = c->default_source_name;
- } else {
- assert(type == PA_NAMEREG_SINK);
+ } else if (type == PA_NAMEREG_SINK) {
if (!c->default_sink_name) {
struct pa_sink *s;
@@ -174,13 +173,15 @@ void* pa_namereg_get(struct pa_core *c, const char *name, enum pa_namereg_type t
d = pa_idxset_get_by_index(c->sinks, index);
else if (type == PA_NAMEREG_SOURCE)
d = pa_idxset_get_by_index(c->sources, index);
-
+ else if (type == PA_NAMEREG_SAMPLE && c->scache)
+ d = pa_idxset_get_by_index(c->scache, index);
+
return d;
}
void pa_namereg_set_default(struct pa_core*c, const char *name, enum pa_namereg_type type) {
char **s;
- assert(c);
+ assert(c && (type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE));
s = type == PA_NAMEREG_SINK ? &c->default_sink_name : &c->default_source_name;
assert(s);
diff --git a/polyp/namereg.h b/polyp/namereg.h
index 5bc92693..b8db1105 100644
--- a/polyp/namereg.h
+++ b/polyp/namereg.h
@@ -26,7 +26,8 @@
enum pa_namereg_type {
PA_NAMEREG_SINK,
- PA_NAMEREG_SOURCE
+ PA_NAMEREG_SOURCE,
+ PA_NAMEREG_SAMPLE
};
void pa_namereg_free(struct pa_core *c);
diff --git a/polyp/polyplib-def.h b/polyp/polyplib-def.h
index 8a506c8d..6420e87e 100644
--- a/polyp/polyplib-def.h
+++ b/polyp/polyplib-def.h
@@ -47,14 +47,14 @@ enum pa_stream_state {
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 */
+ PA_STREAM_TERMINATED /**< The stream has been terminated cleanly */
};
/** The state of an operation */
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 */
+ PA_OPERATION_CANCELED /**< The operation has been canceled */
};
/** An invalid index */
@@ -105,7 +105,7 @@ enum pa_subscription_mask {
PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT = 8, /**< Source output events */
PA_SUBSCRIPTION_MASK_MODULE = 16, /**< Module events */
PA_SUBSCRIPTION_MASK_CLIENT = 32, /**< Client events */
- PA_SUBSCRIPTION_MASK_SAMPLE_CACHE = 64, /**< Sample cache events */
+ PA_SUBSCRIPTION_MASK_SAMPLE_CACHE = 64 /**< Sample cache events */
};
/** Subscription event types, as used by pa_context_subscribe() */
@@ -122,7 +122,7 @@ enum pa_subscription_event_type {
PA_SUBSCRIPTION_EVENT_NEW = 0, /**< A new object was created */
PA_SUBSCRIPTION_EVENT_CHANGE = 16, /**< A property of the object was modified */
PA_SUBSCRIPTION_EVENT_REMOVE = 32, /**< An object was removed */
- PA_SUBSCRIPTION_EVENT_TYPE_MASK = 16+32, /**< A mask to extract the event operation from an event value */
+ PA_SUBSCRIPTION_EVENT_TYPE_MASK = 16+32 /**< A mask to extract the event operation from an event value */
};
/** Return one if an event type t matches an event mask bitfield */
diff --git a/polyp/polyplib-introspect.c b/polyp/polyplib-introspect.c
index 0efc599d..63422383 100644
--- a/polyp/polyplib-introspect.c
+++ b/polyp/polyplib-introspect.c
@@ -580,3 +580,92 @@ struct pa_operation* pa_context_set_sink_input_volume(struct pa_context *c, uint
return pa_operation_ref(o);
}
+
+/** Sample Cache **/
+
+static void context_get_sample_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 (pa_context_handle_error(o->context, command, t) < 0)
+ goto finish;
+
+ eof = -1;
+ } else {
+
+ while (!pa_tagstruct_eof(t)) {
+ struct pa_sample_info i;
+
+ if (pa_tagstruct_getu32(t, &i.index) < 0 ||
+ pa_tagstruct_gets(t, &i.name) < 0 ||
+ pa_tagstruct_getu32(t, &i.volume) < 0 ||
+ pa_tagstruct_getu32(t, &i.duration) < 0 ||
+ pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0) {
+ pa_context_fail(o->context, PA_ERROR_PROTOCOL);
+ goto finish;
+ }
+
+ if (o->callback) {
+ void (*cb)(struct pa_context *s, const struct pa_sample_info*i, int eof, void *userdata) = o->callback;
+ cb(o->context, &i, 0, o->userdata);
+ }
+ }
+ }
+
+ if (o->callback) {
+ void (*cb)(struct pa_context *s, const struct pa_sample_info*i, int eof, void *userdata) = o->callback;
+ cb(o->context, NULL, eof, o->userdata);
+ }
+
+finish:
+ pa_operation_done(o);
+ pa_operation_unref(o);
+}
+
+struct pa_operation* pa_context_get_sample_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sample_info *i, int is_last, void *userdata), void *userdata) {
+ struct pa_tagstruct *t;
+ struct pa_operation *o;
+ uint32_t tag;
+ assert(c && cb && name);
+
+ o = pa_operation_new(c, NULL);
+ o->callback = cb;
+ o->userdata = userdata;
+
+ t = pa_tagstruct_new(NULL, 0);
+ pa_tagstruct_putu32(t, PA_COMMAND_GET_SAMPLE_INFO);
+ pa_tagstruct_putu32(t, tag = c->ctag++);
+ pa_tagstruct_putu32(t, PA_INVALID_INDEX);
+ pa_tagstruct_puts(t, name);
+ pa_pstream_send_tagstruct(c->pstream, t);
+ pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_sample_info_callback, o);
+
+ return pa_operation_ref(o);
+}
+
+struct pa_operation* pa_context_get_sample_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sample_info *i, int is_last, void *userdata), void *userdata) {
+ struct pa_tagstruct *t;
+ struct pa_operation *o;
+ uint32_t tag;
+ assert(c && cb);
+
+ o = pa_operation_new(c, NULL);
+ o->callback = cb;
+ o->userdata = userdata;
+
+ t = pa_tagstruct_new(NULL, 0);
+ pa_tagstruct_putu32(t, PA_COMMAND_GET_SAMPLE_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_sample_info_callback, o);
+
+ return pa_operation_ref(o);
+}
+
+struct pa_operation* pa_context_get_sample_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sample_info *i, int is_last, void *userdata), void *userdata) {
+ return pa_context_send_simple_command(c, PA_COMMAND_GET_SAMPLE_INFO_LIST, context_get_sample_info_callback, cb, userdata);
+}
diff --git a/polyp/polyplib-introspect.h b/polyp/polyplib-introspect.h
index c453eb2f..0cc52549 100644
--- a/polyp/polyplib-introspect.h
+++ b/polyp/polyplib-introspect.h
@@ -139,6 +139,18 @@ struct pa_stat_info {
/** Get daemon memory block statistics */
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);
+struct pa_sample_info {
+ uint32_t index;
+ const char *name;
+ uint32_t volume;
+ struct pa_sample_spec sample_spec;
+ uint32_t duration;
+};
+
+struct pa_operation* pa_context_get_sample_info_by_name(struct pa_context *c, const char *name, void (*cb)(struct pa_context *c, const struct pa_sample_info *i, int is_last, void *userdata), void *userdata);
+struct pa_operation* pa_context_get_sample_info_by_index(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_sample_info *i, int is_last, void *userdata), void *userdata);
+struct pa_operation* pa_context_get_sample_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_sample_info *i, int is_last, void *userdata), void *userdata);
+
PA_C_DECL_END
#endif
diff --git a/polyp/polyplib-operation.h b/polyp/polyplib-operation.h
index ce2756ef..42d5c8e1 100644
--- a/polyp/polyplib-operation.h
+++ b/polyp/polyplib-operation.h
@@ -23,6 +23,7 @@
***/
#include "cdecl.h"
+#include "polyplib-def.h"
/** \file
* Asynchronous operations */
diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c
index 2b591f36..451dd046 100644
--- a/polyp/polyplib-stream.c
+++ b/polyp/polyplib-stream.c
@@ -32,8 +32,8 @@
#include "pstream-util.h"
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;
+ assert(c && ss);
s = pa_xmalloc(sizeof(struct pa_stream));
s->ref = 1;
diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c
index f5efa419..be2ef2b9 100644
--- a/polyp/protocol-esound.c
+++ b/polyp/protocol-esound.c
@@ -427,7 +427,7 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v
k = sizeof(int)*5+ESD_NAME_MAX;
s = sizeof(int)*6+ESD_NAME_MAX;
- nsamples = c->protocol->core->scache_idxset ? pa_idxset_ncontents(c->protocol->core->scache_idxset) : 0;
+ nsamples = c->protocol->core->scache ? pa_idxset_ncontents(c->protocol->core->scache) : 0;
response = connection_write(c, (t = s*(nsamples+1) + k*(c->protocol->n_player+1)));
assert(k);
@@ -482,7 +482,7 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v
struct pa_scache_entry *ce;
index = PA_IDXSET_INVALID;
- for (ce = pa_idxset_first(c->protocol->core->scache_idxset, &index); ce; ce = pa_idxset_next(c->protocol->core->scache_idxset, &index)) {
+ for (ce = pa_idxset_first(c->protocol->core->scache, &index); ce; ce = pa_idxset_next(c->protocol->core->scache, &index)) {
assert(t >= s*2);
/* id */
diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c
index 060b4241..d633c265 100644
--- a/polyp/protocol-native.c
+++ b/polyp/protocol-native.c
@@ -164,12 +164,14 @@ static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = {
[PA_COMMAND_GET_MODULE_INFO] = { command_get_info },
[PA_COMMAND_GET_SINK_INPUT_INFO] = { command_get_info },
[PA_COMMAND_GET_SOURCE_OUTPUT_INFO] = { command_get_info },
+ [PA_COMMAND_GET_SAMPLE_INFO] = { command_get_info },
[PA_COMMAND_GET_SINK_INFO_LIST] = { command_get_info_list },
[PA_COMMAND_GET_SOURCE_INFO_LIST] = { command_get_info_list },
[PA_COMMAND_GET_MODULE_INFO_LIST] = { command_get_info_list },
[PA_COMMAND_GET_CLIENT_INFO_LIST] = { command_get_info_list },
[PA_COMMAND_GET_SINK_INPUT_INFO_LIST] = { command_get_info_list },
[PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST] = { command_get_info_list },
+ [PA_COMMAND_GET_SAMPLE_INFO_LIST] = { command_get_info_list },
[PA_COMMAND_GET_SERVER_INFO] = { command_get_server_info },
[PA_COMMAND_SUBSCRIBE] = { command_subscribe },
[PA_COMMAND_SET_SINK_VOLUME] = { command_set_volume },
@@ -763,8 +765,8 @@ static void command_drain_playback_stream(struct pa_pdispatch *pd, uint32_t comm
static void command_stat(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
struct connection *c = userdata;
- assert(c && t);
struct pa_tagstruct *reply;
+ assert(c && t);
if (!pa_tagstruct_eof(t)) {
protocol_error(c);
@@ -789,10 +791,10 @@ static void command_stat(struct pa_pdispatch *pd, uint32_t command, uint32_t tag
static void command_get_playback_latency(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
struct connection *c = userdata;
- assert(c && t);
struct pa_tagstruct *reply;
struct playback_stream *s;
uint32_t index, latency;
+ assert(c && t);
if (pa_tagstruct_getu32(t, &index) < 0 ||
!pa_tagstruct_eof(t)) {
@@ -1021,6 +1023,15 @@ static void source_output_fill_tagstruct(struct pa_tagstruct *t, struct pa_sourc
pa_tagstruct_put_sample_spec(t, &s->sample_spec);
}
+static void scache_fill_tagstruct(struct pa_tagstruct *t, struct pa_scache_entry *e) {
+ assert(t && e);
+ pa_tagstruct_putu32(t, e->index);
+ pa_tagstruct_puts(t, e->name);
+ pa_tagstruct_putu32(t, e->volume);
+ pa_tagstruct_putu32(t, pa_bytes_to_usec(e->memchunk.length, &e->sample_spec));
+ pa_tagstruct_put_sample_spec(t, &e->sample_spec);
+}
+
static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
struct connection *c = userdata;
uint32_t index;
@@ -1030,6 +1041,7 @@ static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t
struct pa_module *module = NULL;
struct pa_sink_input *si = NULL;
struct pa_source_output *so = NULL;
+ struct pa_scache_entry *sce = NULL;
const char *name;
struct pa_tagstruct *reply;
assert(c && t);
@@ -1067,12 +1079,17 @@ static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t
module = pa_idxset_get_by_index(c->protocol->core->modules, index);
else if (command == PA_COMMAND_GET_SINK_INPUT_INFO)
si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, index);
- else {
- assert(command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO);
+ else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO)
so = pa_idxset_get_by_index(c->protocol->core->source_outputs, index);
+ else {
+ assert(command == PA_COMMAND_GET_SAMPLE_INFO && name);
+ if (index != (uint32_t) -1)
+ sce = pa_idxset_get_by_index(c->protocol->core->scache, index);
+ else
+ sce = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SAMPLE, 0);
}
- if (!sink && !source && !client && !module && !si && !so) {
+ if (!sink && !source && !client && !module && !si && !so && !sce) {
pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
return;
}
@@ -1091,8 +1108,10 @@ static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t
module_fill_tagstruct(reply, module);
else if (si)
sink_input_fill_tagstruct(reply, si);
- else
+ else if (so)
source_output_fill_tagstruct(reply, so);
+ else
+ scache_fill_tagstruct(reply, sce);
pa_pstream_send_tagstruct(c->pstream, reply);
}
@@ -1129,11 +1148,13 @@ static void command_get_info_list(struct pa_pdispatch *pd, uint32_t command, uin
i = c->protocol->core->modules;
else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST)
i = c->protocol->core->sink_inputs;
- else {
- assert(command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST);
+ else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST)
i = c->protocol->core->source_outputs;
+ else {
+ assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST);
+ i = c->protocol->core->scache;
}
-
+
for (p = pa_idxset_first(i, &index); p; p = pa_idxset_next(i, &index)) {
if (command == PA_COMMAND_GET_SINK_INFO_LIST)
sink_fill_tagstruct(reply, p);
@@ -1145,9 +1166,11 @@ static void command_get_info_list(struct pa_pdispatch *pd, uint32_t command, uin
module_fill_tagstruct(reply, p);
else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST)
sink_input_fill_tagstruct(reply, p);
- else {
- assert(command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST);
+ else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST)
source_output_fill_tagstruct(reply, p);
+ else {
+ assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST);
+ scache_fill_tagstruct(reply, p);
}
}
diff --git a/polyp/sample.c b/polyp/sample.c
index 173de9c1..f4a80861 100644
--- a/polyp/sample.c
+++ b/polyp/sample.c
@@ -29,8 +29,8 @@
#include "sample.h"
size_t pa_frame_size(const struct pa_sample_spec *spec) {
- assert(spec);
size_t b = 1;
+ assert(spec);
switch (spec->format) {
case PA_SAMPLE_U8:
diff --git a/polyp/scache.c b/polyp/scache.c
index f0d261f6..f3c15934 100644
--- a/polyp/scache.c
+++ b/polyp/scache.c
@@ -35,9 +35,11 @@
#include "play-memchunk.h"
#include "xmalloc.h"
#include "subscribe.h"
+#include "namereg.h"
static void free_entry(struct pa_scache_entry *e) {
assert(e);
+ pa_namereg_unregister(e->core, e->name);
pa_subscription_post(e->core, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_REMOVE, e->index);
pa_xfree(e->name);
if (e->memchunk.memblock)
@@ -45,25 +47,32 @@ static void free_entry(struct pa_scache_entry *e) {
pa_xfree(e);
}
-void pa_scache_add_item(struct pa_core *c, const char *name, struct pa_sample_spec *ss, struct pa_memchunk *chunk, uint32_t *index) {
+int pa_scache_add_item(struct pa_core *c, const char *name, struct pa_sample_spec *ss, struct pa_memchunk *chunk, uint32_t *index) {
struct pa_scache_entry *e;
int put;
assert(c && name);
- if (c->scache_hashmap && (e = pa_hashmap_get(c->scache_hashmap, name))) {
+ if ((e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 0))) {
put = 0;
if (e->memchunk.memblock)
pa_memblock_unref(e->memchunk.memblock);
assert(e->core == c);
} else {
+
put = 1;
e = pa_xmalloc(sizeof(struct pa_scache_entry));
+
+ if (!pa_namereg_register(c, name, PA_NAMEREG_SAMPLE, e, 1)) {
+ pa_xfree(e);
+ return -1;
+ }
+
e->name = pa_xstrdup(name);
e->core = c;
}
- e->volume = 0x100;
-
+ e->volume = PA_VOLUME_NORM;
+
if (ss)
e->sample_spec = *ss;
else
@@ -78,35 +87,31 @@ void pa_scache_add_item(struct pa_core *c, const char *name, struct pa_sample_sp
}
if (put) {
- if (!c->scache_hashmap) {
- c->scache_hashmap = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
- assert(c->scache_hashmap);
- }
-
- if (!c->scache_idxset) {
- c->scache_idxset = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
- assert(c->scache_idxset);
+ if (!c->scache) {
+ c->scache = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
+ assert(c->scache);
}
- pa_idxset_put(c->scache_idxset, e, &e->index);
- pa_hashmap_put(c->scache_hashmap, e->name, e);
+ pa_idxset_put(c->scache, e, &e->index);
pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_NEW, e->index);
- }
+ } else
+ pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_CHANGE, e->index);
if (index)
*index = e->index;
+
+ return 0;
}
int pa_scache_remove_item(struct pa_core *c, const char *name) {
struct pa_scache_entry *e;
assert(c && name);
- if (!c->scache_hashmap || !(e = pa_hashmap_get(c->scache_hashmap, name)))
+ if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 0)))
return -1;
- pa_hashmap_remove(c->scache_hashmap, name);
- if (pa_idxset_remove_by_data(c->scache_idxset, e, NULL) != e)
+ if (pa_idxset_remove_by_data(c->scache, e, NULL) != e)
assert(0);
free_entry(e);
@@ -122,14 +127,9 @@ static void free_cb(void *p, void *userdata) {
void pa_scache_free(struct pa_core *c) {
assert(c);
- if (c->scache_hashmap) {
- pa_hashmap_free(c->scache_hashmap, free_cb, NULL);
- c->scache_hashmap = NULL;
- }
-
- if (c->scache_idxset) {
- pa_idxset_free(c->scache_idxset, NULL, NULL);
- c->scache_idxset = NULL;
+ if (c->scache) {
+ pa_idxset_free(c->scache, free_cb, NULL);
+ c->scache = NULL;
}
}
@@ -137,7 +137,7 @@ int pa_scache_play_item(struct pa_core *c, const char *name, struct pa_sink *sin
struct pa_scache_entry *e;
assert(c && name && sink);
- if (!c->scache_hashmap || !(e = pa_hashmap_get(c->scache_hashmap, name)))
+ if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 0)))
return -1;
if (!e->memchunk.memblock)
@@ -153,19 +153,9 @@ const char * pa_scache_get_name_by_id(struct pa_core *c, uint32_t id) {
struct pa_scache_entry *e;
assert(c && id != PA_IDXSET_INVALID);
- if (!c->scache_idxset || !(e = pa_idxset_get_by_index(c->scache_idxset, id)))
+ if (!c->scache || !(e = pa_idxset_get_by_index(c->scache, id)))
return NULL;
return e->name;
}
-
-uint32_t pa_scache_get_id_by_name(struct pa_core *c, const char *name) {
- struct pa_scache_entry *e;
- assert(c && name);
-
- if (!c->scache_hashmap || !(e = pa_hashmap_get(c->scache_hashmap, name)))
- return PA_IDXSET_INVALID;
-
- return e->index;
-}
diff --git a/polyp/scache.h b/polyp/scache.h
index 8ccca156..959067f3 100644
--- a/polyp/scache.h
+++ b/polyp/scache.h
@@ -35,7 +35,7 @@ struct pa_scache_entry {
struct pa_memchunk memchunk;
};
-void pa_scache_add_item(struct pa_core *c, const char *name, struct pa_sample_spec *ss, struct pa_memchunk *chunk, uint32_t *index);
+int pa_scache_add_item(struct pa_core *c, const char *name, struct pa_sample_spec *ss, struct pa_memchunk *chunk, uint32_t *index);
int pa_scache_remove_item(struct pa_core *c, const char *name);
int pa_scache_play_item(struct pa_core *c, const char *name, struct pa_sink *sink, uint32_t volume);
diff --git a/polyp/strbuf.c b/polyp/strbuf.c
index 169604e8..ef48a3fb 100644
--- a/polyp/strbuf.c
+++ b/polyp/strbuf.c
@@ -36,7 +36,7 @@
struct chunk {
struct chunk *next;
size_t length;
- char text[];
+ char text[0];
};
struct pa_strbuf {
diff --git a/polyp/strbuf.h b/polyp/strbuf.h
index d672c42a..8ca51624 100644
--- a/polyp/strbuf.h
+++ b/polyp/strbuf.h
@@ -29,7 +29,7 @@ void pa_strbuf_free(struct pa_strbuf *sb);
char *pa_strbuf_tostring(struct pa_strbuf *sb);
char *pa_strbuf_tostring_free(struct pa_strbuf *sb);
-int pa_strbuf_printf(struct pa_strbuf *sb, const char *format, ...) __attribute__ ((format (printf, 2, 3)));;
+int pa_strbuf_printf(struct pa_strbuf *sb, const char *format, ...) __attribute__ ((format (printf, 2, 3)));
void pa_strbuf_puts(struct pa_strbuf *sb, const char *t);
void pa_strbuf_putsn(struct pa_strbuf *sb, const char *t, size_t m);