mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-29 05:40:23 -04:00
move sample cache to namereg
documentation git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@141 fefdeb5f-60dc-0310-8127-8f9354f1896f
This commit is contained in:
parent
e0fe68a2d4
commit
f9b58fb0ea
27 changed files with 252 additions and 136 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 <@PACKAGE_BUGREPORT@>, July 2004</address>
|
||||
<address class="grey">Lennart Poettering <@PACKAGE_BUGREPORT@>, August 2004</address>
|
||||
<div class="grey"><i>$Id$</i></div>
|
||||
|
||||
</body>
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
***/
|
||||
|
||||
#include "cdecl.h"
|
||||
#include "polyplib-def.h"
|
||||
|
||||
/** \file
|
||||
* Asynchronous operations */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
c->scache = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
|
||||
assert(c->scache);
|
||||
}
|
||||
|
||||
if (!c->scache_idxset) {
|
||||
c->scache_idxset = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
|
||||
assert(c->scache_idxset);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
struct chunk {
|
||||
struct chunk *next;
|
||||
size_t length;
|
||||
char text[];
|
||||
char text[0];
|
||||
};
|
||||
|
||||
struct pa_strbuf {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue