move sample cache to namereg
authorLennart Poettering <lennart@poettering.net>
Thu, 19 Aug 2004 23:14:59 +0000 (23:14 +0000)
committerLennart Poettering <lennart@poettering.net>
Thu, 19 Aug 2004 23:14:59 +0000 (23:14 +0000)
documentation

git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@141 fefdeb5f-60dc-0310-8127-8f9354f1896f

27 files changed:
configure.ac
doc/README.html.in
polyp/cli-text.c
polyp/core.c
polyp/core.h
polyp/glib-mainloop.c
polyp/llist.h
polyp/mainloop-api.h
polyp/mainloop.c
polyp/memblockq.c
polyp/memchunk.c
polyp/module-oss-mmap.c
polyp/module-oss.c
polyp/namereg.c
polyp/namereg.h
polyp/polyplib-def.h
polyp/polyplib-introspect.c
polyp/polyplib-introspect.h
polyp/polyplib-operation.h
polyp/polyplib-stream.c
polyp/protocol-esound.c
polyp/protocol-native.c
polyp/sample.c
polyp/scache.c
polyp/scache.h
polyp/strbuf.c
polyp/strbuf.h

index a8c4526..96b4cf3 100644 (file)
@@ -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
index 296d450..4972c19 100644 (file)
@@ -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>
index 000d6d3..fa1ccdf 100644 (file)
@@ -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);
index b43eb63..908564c 100644 (file)
@@ -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);    
-};
+}
 
index c0a2d6d..a297d4e 100644 (file)
@@ -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;
 
index a91f48e..4fee0a4 100644 (file)
@@ -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) {
index 12a33e9..ec8e029 100644 (file)
@@ -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)
 
index e631c7a..43d150e 100644 (file)
@@ -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
index c678537..84505bb 100644 (file)
@@ -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;
index bc5d743..085c051 100644 (file)
@@ -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;
index 5913c6e..920189e 100644 (file)
@@ -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;
index 7c7750d..05e0617 100644 (file)
@@ -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;
index d5517b5..3fa3d1e 100644 (file)
@@ -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;
index b6a8c23..72a4c64 100644 (file)
@@ -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);
index 5bc9269..b8db110 100644 (file)
@@ -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);
index 8a506c8..6420e87 100644 (file)
@@ -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 */
index 0efc599..6342238 100644 (file)
@@ -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);
+}
index c453eb2..0cc5254 100644 (file)
@@ -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
index ce2756e..42d5c8e 100644 (file)
@@ -23,6 +23,7 @@
 ***/
 
 #include "cdecl.h"
+#include "polyplib-def.h"
 
 /** \file
  * Asynchronous operations */
index 2b591f3..451dd04 100644 (file)
@@ -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;
index f5efa41..be2ef2b 100644 (file)
@@ -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 */
index 060b424..d633c26 100644 (file)
@@ -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);
         }
     } 
     
index 173de9c..f4a8086 100644 (file)
@@ -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:
index f0d261f..f3c1593 100644 (file)
 #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;
-}
index 8ccca15..959067f 100644 (file)
@@ -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);
index 169604e..ef48a3f 100644 (file)
@@ -36,7 +36,7 @@
 struct chunk {
     struct chunk *next;
     size_t length;
-    char text[];
+    char text[0];
 };
 
 struct pa_strbuf {
index d672c42..8ca5162 100644 (file)
@@ -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);