From f9b58fb0eafdc332e500a0851b0506146c2b14cd Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 19 Aug 2004 23:14:59 +0000 Subject: move sample cache to namereg documentation git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@141 fefdeb5f-60dc-0310-8127-8f9354f1896f --- configure.ac | 2 +- doc/README.html.in | 41 +++++++++++---------- polyp/cli-text.c | 8 ++-- polyp/core.c | 9 ++--- polyp/core.h | 4 +- polyp/glib-mainloop.c | 28 +++++++------- polyp/llist.h | 2 +- polyp/mainloop-api.h | 2 +- polyp/mainloop.c | 37 +++++++++---------- polyp/memblockq.c | 2 +- polyp/memchunk.c | 2 +- polyp/module-oss-mmap.c | 2 +- polyp/module-oss.c | 2 +- polyp/namereg.c | 9 +++-- polyp/namereg.h | 3 +- polyp/polyplib-def.h | 8 ++-- polyp/polyplib-introspect.c | 89 +++++++++++++++++++++++++++++++++++++++++++++ polyp/polyplib-introspect.h | 12 ++++++ polyp/polyplib-operation.h | 1 + polyp/polyplib-stream.c | 2 +- polyp/protocol-esound.c | 4 +- polyp/protocol-native.c | 45 +++++++++++++++++------ polyp/sample.c | 2 +- polyp/scache.c | 66 ++++++++++++++------------------- polyp/scache.h | 2 +- polyp/strbuf.c | 2 +- polyp/strbuf.h | 2 +- 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.

News

+
Fri Aug 20 2004:

Version 0.2 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.

Sat Jul 17 2004:

Version 0.1 released

@@ -56,7 +60,7 @@ Daemon (ESOUND). In addition to the features ESOUND provides polypaudio has:

Both the core and the client API are completely asynchronous making @@ -74,31 +79,27 @@ available through polyplib is quite difficult to use there is a simplified synchronous API wrapper polyplib-simple available. A simple main loop implementation is available as well.

-

polypaudio is the successor of my previous, ill-fated attempt to write a sound server asd.

+

polypaudio is the successor of my previous, ill-fated +attempt to write a sound server asd.

+ +

A GTK GUI manager application for polypaudio is the Polypaudio Manager.

Status

-

Version @PACKAGE_VERSION@ is quite usable. polypaudio 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 TODO -list.

+

Version @PACKAGE_VERSION@ is quite usable. It matches and supersedes ESOUND's feature set in nearly all areas.

Documentation

-

There is some prelimenary documentation available: There is some preliminary documentation available: modules.html, cli.html, daemeon.html.

+href="daemon.html">daemon.html.

-

Documentation for developing with polypaudio is not yet -available. Read the source, Luke! There are some example application -available: for the asynchronous -API and for the simple, -synchronous API.

+

You may browser the Doxygen generated programing +documentation for the client API. (Run make doxygen to generate this documentation from the source tree)

First Steps

@@ -131,7 +132,9 @@ GNU libtool for source code configuration and shared library management.

polypaudio needs Secret Rabbit Code (aka libsamplerate) and alsa-lib.

+href="http://www.mega-nerd.com/SRC/">Secret Rabbit Code (aka +libsamplerate), libsndfile and alsa-lib.

Installation

@@ -156,7 +159,7 @@ compilation and make install (as root) for installation of

If you want to be notified whenever I release a new version of this software use the subscription feature of Freshmeat.


-
Lennart Poettering <@PACKAGE_BUGREPORT@>, July 2004
+
Lennart Poettering <@PACKAGE_BUGREPORT@>, August 2004
$Id$
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); -- cgit