mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-29 05:40:23 -04:00
add support for module search path as command line argument
protocol-native: move first data request into ack of stream creation improve mainloop API: return the number of dispatched sources on iterate() fix a resampling bug introduce network latency measurement WARNING: all these changes together may break some applications git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@189 fefdeb5f-60dc-0310-8127-8f9354f1896f
This commit is contained in:
parent
0c99fb3182
commit
25123469d5
20 changed files with 210 additions and 60 deletions
|
|
@ -20,7 +20,7 @@
|
|||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
AC_PREREQ(2.57)
|
||||
AC_INIT([polypaudio],[0.4],[mzcbylcnhqvb (at) 0pointer (dot) de])
|
||||
AC_INIT([polypaudio],[0.5],[mzcbylcnhqvb (at) 0pointer (dot) de])
|
||||
AC_CONFIG_SRCDIR([polyp/main.c])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AM_INIT_AUTOMAKE([foreign -Wall])
|
||||
|
|
|
|||
14
doc/todo
14
doc/todo
|
|
@ -12,6 +12,13 @@
|
|||
- add sample directory
|
||||
- config file for command line arguments
|
||||
- option to use default fragment size on alsa drivers
|
||||
- keep volume in xmms-polyp (and allow volume changing when not playing)
|
||||
- lazy sample cache
|
||||
- per-channel volume
|
||||
- add version number to library names
|
||||
- extend pa_usec_t to 64 bit
|
||||
- make use of network latency in all apps
|
||||
- rename streams/contexts
|
||||
|
||||
** later ***
|
||||
- xmlrpc/http
|
||||
|
|
@ -23,7 +30,8 @@
|
|||
***********
|
||||
|
||||
backends for:
|
||||
- mplayer
|
||||
- sdl
|
||||
- gstreamer
|
||||
- portaudio
|
||||
- sdl
|
||||
- gstreamer (semi-done)
|
||||
- alsa-lib
|
||||
- OSS (esddsp style)
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ void pa_cmdline_help(const char *argv0) {
|
|||
" -X SECS Terminate the daemon after the last client quit and this time passed\n"
|
||||
" -h Show this help\n"
|
||||
" -l TARGET Specify the log target (syslog, stderr, auto)\n"
|
||||
" -p DIR Append a directory to the search path for dynamic modules\n"
|
||||
" -V Show version\n", e, cfg);
|
||||
|
||||
pa_xfree(cfg);
|
||||
|
|
@ -101,11 +102,12 @@ struct pa_cmdline* pa_cmdline_parse(int argc, char * const argv []) {
|
|||
cmdline->fail = cmdline->auto_log_target = 1;
|
||||
cmdline->quit_after_last_client_time = -1;
|
||||
cmdline->log_target = -1;
|
||||
cmdline->dl_searchdir = NULL;
|
||||
|
||||
buf = pa_strbuf_new();
|
||||
assert(buf);
|
||||
|
||||
while ((c = getopt(argc, argv, "L:F:CDhfvrRVndX:l:")) != -1) {
|
||||
while ((c = getopt(argc, argv, "L:F:CDhfvrRVndX:l:p:")) != -1) {
|
||||
switch (c) {
|
||||
case 'L':
|
||||
pa_strbuf_printf(buf, "load %s\n", optarg);
|
||||
|
|
@ -146,6 +148,11 @@ struct pa_cmdline* pa_cmdline_parse(int argc, char * const argv []) {
|
|||
case 'X':
|
||||
cmdline->quit_after_last_client_time = atoi(optarg);
|
||||
break;
|
||||
case 'p':
|
||||
if (cmdline->dl_searchdir)
|
||||
pa_xfree(cmdline->dl_searchdir);
|
||||
cmdline->dl_searchdir = pa_xstrdup(optarg);
|
||||
break;
|
||||
case 'l':
|
||||
if (!strcmp(optarg, "syslog")) {
|
||||
cmdline->auto_log_target = 0;
|
||||
|
|
@ -185,5 +192,6 @@ fail:
|
|||
void pa_cmdline_free(struct pa_cmdline *cmd) {
|
||||
assert(cmd);
|
||||
pa_xfree(cmd->cli_commands);
|
||||
pa_xfree(cmd->dl_searchdir);
|
||||
pa_xfree(cmd);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ struct pa_cmdline {
|
|||
quit_after_last_client_time,
|
||||
auto_log_target;
|
||||
char *cli_commands;
|
||||
char *dl_searchdir;
|
||||
enum pa_log_target log_target;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -180,6 +180,10 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
r = lt_dlinit();
|
||||
assert(r == 0);
|
||||
|
||||
if (cmdline->dl_searchdir)
|
||||
lt_dladdsearchdir(cmdline->dl_searchdir);
|
||||
|
||||
#ifdef DLSEARCHDIR
|
||||
lt_dladdsearchdir(DLSEARCHDIR);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -378,9 +378,10 @@ static void rebuild_pollfds(struct pa_mainloop *m) {
|
|||
}
|
||||
}
|
||||
|
||||
static void dispatch_pollfds(struct pa_mainloop *m) {
|
||||
static int dispatch_pollfds(struct pa_mainloop *m) {
|
||||
uint32_t index = PA_IDXSET_INVALID;
|
||||
struct pa_io_event *e;
|
||||
int r = 0;
|
||||
|
||||
for (e = pa_idxset_first(m->io_events, &index); e; e = pa_idxset_next(m->io_events, &index)) {
|
||||
if (e->dead || !e->pollfd || !e->pollfd->revents)
|
||||
|
|
@ -394,12 +395,16 @@ static void dispatch_pollfds(struct pa_mainloop *m) {
|
|||
(e->pollfd->revents & POLLERR ? PA_IO_EVENT_ERROR : 0),
|
||||
e->userdata);
|
||||
e->pollfd->revents = 0;
|
||||
r++;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void dispatch_defer(struct pa_mainloop *m) {
|
||||
static int dispatch_defer(struct pa_mainloop *m) {
|
||||
uint32_t index;
|
||||
struct pa_defer_event *e;
|
||||
int r = 0;
|
||||
|
||||
for (e = pa_idxset_first(m->defer_events, &index); e; e = pa_idxset_next(m->defer_events, &index)) {
|
||||
if (e->dead || !e->enabled)
|
||||
|
|
@ -407,7 +412,10 @@ static void dispatch_defer(struct pa_mainloop *m) {
|
|||
|
||||
assert(e->callback);
|
||||
e->callback(&m->api, e, e->userdata);
|
||||
r++;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int calc_next_timeout(struct pa_mainloop *m) {
|
||||
|
|
@ -451,15 +459,16 @@ static int calc_next_timeout(struct pa_mainloop *m) {
|
|||
return t;
|
||||
}
|
||||
|
||||
static void dispatch_timeout(struct pa_mainloop *m) {
|
||||
static int dispatch_timeout(struct pa_mainloop *m) {
|
||||
uint32_t index;
|
||||
struct pa_time_event *e;
|
||||
struct timeval now;
|
||||
int got_time = 0;
|
||||
int r = 0;
|
||||
assert(m);
|
||||
|
||||
if (pa_idxset_isempty(m->time_events))
|
||||
return;
|
||||
return 0;
|
||||
|
||||
for (e = pa_idxset_first(m->time_events, &index); e; e = pa_idxset_next(m->time_events, &index)) {
|
||||
|
||||
|
|
@ -477,51 +486,66 @@ static void dispatch_timeout(struct pa_mainloop *m) {
|
|||
|
||||
e->enabled = 0;
|
||||
e->callback(&m->api, e, &e->timeval, e->userdata);
|
||||
|
||||
r++;
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int pa_mainloop_iterate(struct pa_mainloop *m, int block, int *retval) {
|
||||
int r;
|
||||
int r, t, dispatched = 0;
|
||||
assert(m && !m->running);
|
||||
|
||||
if(m->quit) {
|
||||
if (retval)
|
||||
*retval = m->retval;
|
||||
return 1;
|
||||
return -2;
|
||||
}
|
||||
|
||||
m->running = 1;
|
||||
|
||||
scan_dead(m);
|
||||
dispatch_defer(m);
|
||||
dispatched += dispatch_defer(m);
|
||||
|
||||
if (m->rebuild_pollfds) {
|
||||
rebuild_pollfds(m);
|
||||
m->rebuild_pollfds = 0;
|
||||
}
|
||||
|
||||
do {
|
||||
int t = block ? calc_next_timeout(m) : 0;
|
||||
/*pa_log(__FILE__": %u\n", t);*/
|
||||
r = poll(m->pollfds, m->n_pollfds, t);
|
||||
} while (r < 0 && errno == EINTR);
|
||||
t = block ? calc_next_timeout(m) : 0;
|
||||
r = poll(m->pollfds, m->n_pollfds, t);
|
||||
|
||||
dispatch_timeout(m);
|
||||
|
||||
if (r > 0)
|
||||
dispatch_pollfds(m);
|
||||
else if (r < 0)
|
||||
pa_log(__FILE__": select(): %s\n", strerror(errno));
|
||||
if (r < 0) {
|
||||
if (errno == EINTR)
|
||||
r = 0;
|
||||
else
|
||||
pa_log(__FILE__": select(): %s\n", strerror(errno));
|
||||
} else {
|
||||
dispatched += dispatch_timeout(m);
|
||||
|
||||
if (r > 0)
|
||||
dispatched += dispatch_pollfds(m);
|
||||
}
|
||||
|
||||
m->running = 0;
|
||||
return r < 0 ? -1 : 0;
|
||||
|
||||
/* pa_log("dispatched: %i\n", dispatched); */
|
||||
|
||||
return r < 0 ? -1 : dispatched;
|
||||
}
|
||||
|
||||
int pa_mainloop_run(struct pa_mainloop *m, int *retval) {
|
||||
int r;
|
||||
while ((r = pa_mainloop_iterate(m, 1, retval)) == 0);
|
||||
return r;
|
||||
while ((r = pa_mainloop_iterate(m, 1, retval)) >= 0);
|
||||
|
||||
if (r == -2)
|
||||
return 1;
|
||||
else if (r < 0)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pa_mainloop_quit(struct pa_mainloop *m, int r) {
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ void pa_mainloop_free(struct pa_mainloop* m);
|
|||
on error or exit request. If block is nonzero, block for events if
|
||||
none are queued. Optionally return the return value as specified with
|
||||
the main loop's quit() routine in the integer variable retval points
|
||||
to */
|
||||
to. On success returns the number of source dispatched in this iteration. */
|
||||
int pa_mainloop_iterate(struct pa_mainloop *m, int block, int *retval);
|
||||
|
||||
/** Run unlimited iterations of the main loop object until the main loop's quit() routine is called. */
|
||||
|
|
|
|||
|
|
@ -149,9 +149,9 @@ int pa_memblockq_peek(struct pa_memblockq* bq, struct pa_memchunk *chunk) {
|
|||
void pa_memblockq_drop(struct pa_memblockq *bq, const struct pa_memchunk *chunk, size_t length) {
|
||||
assert(bq && chunk && length);
|
||||
|
||||
if (!bq->blocks || memcmp(&bq->blocks->chunk, chunk, sizeof(struct pa_memchunk)))
|
||||
if (!bq->blocks || memcmp(&bq->blocks->chunk, chunk, sizeof(struct pa_memchunk)))
|
||||
return;
|
||||
|
||||
|
||||
assert(length <= bq->blocks->chunk.length);
|
||||
pa_memblockq_skip(bq, length);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -431,11 +431,10 @@ void pa_context_set_state_callback(struct pa_context *c, void (*cb)(struct pa_co
|
|||
int pa_context_is_pending(struct pa_context *c) {
|
||||
assert(c && c->ref >= 1);
|
||||
|
||||
if (c->state != PA_CONTEXT_READY)
|
||||
return 0;
|
||||
|
||||
assert(c->pstream && c->pdispatch);
|
||||
return pa_pstream_is_pending(c->pstream) || pa_pdispatch_is_pending(c->pdispatch);
|
||||
/* pa_log("pstream: %i\n", pa_pstream_is_pending(c->pstream)); */
|
||||
/* pa_log("pdispatch: %i\n", pa_pdispatch_is_pending(c->pdispatch)); */
|
||||
|
||||
return (c->pstream && pa_pstream_is_pending(c->pstream)) || (c->pdispatch && pa_pdispatch_is_pending(c->pdispatch)) || c->client;
|
||||
}
|
||||
|
||||
static void set_dispatch_callbacks(struct pa_operation *o);
|
||||
|
|
|
|||
|
|
@ -133,7 +133,8 @@ enum pa_subscription_event_type {
|
|||
|
||||
/** A structure for latency info. See pa_stream_get_latency(). The
|
||||
* total latency a sample that is written with pa_stream_write() takes
|
||||
* to be played is buffer_usec+sink_usec. The buffer to which
|
||||
* to be played may be estimated by
|
||||
* buffer_usec+sink_usec+transport_usec. The buffer to which
|
||||
* buffer_usec relates may be manipulated freely (with
|
||||
* pa_stream_write()'s delta argument, pa_stream_flush() and friends),
|
||||
* the playback buffer sink_usec relates to is a FIFO which cannot be
|
||||
|
|
@ -141,6 +142,7 @@ enum pa_subscription_event_type {
|
|||
struct pa_latency_info {
|
||||
pa_usec_t buffer_usec; /**< Time in usecs the current buffer takes to play */
|
||||
pa_usec_t sink_usec; /**< Time in usecs a sample takes to be played on the sink. */
|
||||
pa_usec_t transport_usec; /**< Estimated time in usecs a sample takes to be transferred to the daemon. \since 0.5 */
|
||||
int playing; /**< Non-zero when the stream is currently playing */
|
||||
uint32_t queue_length; /**< Queue size in bytes. */
|
||||
};
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "polyplib-internal.h"
|
||||
#include "xmalloc.h"
|
||||
#include "pstream-util.h"
|
||||
#include "util.h"
|
||||
|
||||
struct pa_stream *pa_stream_new(struct pa_context *c, const char *name, const struct pa_sample_spec *ss) {
|
||||
struct pa_stream *s;
|
||||
|
|
@ -193,6 +194,7 @@ void pa_create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32
|
|||
|
||||
if (pa_tagstruct_getu32(t, &s->channel) < 0 ||
|
||||
((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) ||
|
||||
((s->direction == PA_STREAM_PLAYBACK) && pa_tagstruct_getu32(t, &s->requested_bytes) < 0) ||
|
||||
!pa_tagstruct_eof(t)) {
|
||||
pa_context_fail(s->context, PA_ERROR_PROTOCOL);
|
||||
goto finish;
|
||||
|
|
@ -202,6 +204,9 @@ void pa_create_stream_callback(struct pa_pdispatch *pd, uint32_t command, uint32
|
|||
pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s);
|
||||
pa_stream_set_state(s, PA_STREAM_READY);
|
||||
|
||||
if (s->requested_bytes && s->ref > 1 && s->write_callback)
|
||||
s->write_callback(s, s->requested_bytes, s->write_userdata);
|
||||
|
||||
finish:
|
||||
pa_stream_unref(s);
|
||||
}
|
||||
|
|
@ -321,6 +326,7 @@ struct pa_operation * pa_stream_drain(struct pa_stream *s, void (*cb) (struct pa
|
|||
static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) {
|
||||
struct pa_operation *o = userdata;
|
||||
struct pa_latency_info i, *p = NULL;
|
||||
struct timeval local, remote, now;
|
||||
assert(pd && o && o->stream && o->context);
|
||||
|
||||
if (command != PA_COMMAND_REPLY) {
|
||||
|
|
@ -331,12 +337,23 @@ static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t comman
|
|||
pa_tagstruct_getu32(t, &i.sink_usec) < 0 ||
|
||||
pa_tagstruct_get_boolean(t, &i.playing) < 0 ||
|
||||
pa_tagstruct_getu32(t, &i.queue_length) < 0 ||
|
||||
pa_tagstruct_get_timeval(t, &local) < 0 ||
|
||||
pa_tagstruct_get_timeval(t, &remote) < 0 ||
|
||||
!pa_tagstruct_eof(t)) {
|
||||
pa_context_fail(o->context, PA_ERROR_PROTOCOL);
|
||||
goto finish;
|
||||
} else
|
||||
p = &i;
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
|
||||
if (pa_timeval_cmp(&local, &remote) < 0 && pa_timeval_cmp(&remote, &now))
|
||||
/* local and remote seem to have synchronized clocks */
|
||||
i.transport_usec = pa_timeval_diff(&remote, &local);
|
||||
else
|
||||
/* clocks are not synchronized, let's estimate latency then */
|
||||
i.transport_usec = pa_timeval_diff(&now, &local)/2;
|
||||
|
||||
if (o->callback) {
|
||||
void (*cb)(struct pa_stream *s, const struct pa_latency_info *i, void *userdata) = o->callback;
|
||||
cb(o->stream, p, o->userdata);
|
||||
|
|
@ -351,6 +368,7 @@ struct pa_operation* pa_stream_get_latency(struct pa_stream *s, void (*cb)(struc
|
|||
uint32_t tag;
|
||||
struct pa_operation *o;
|
||||
struct pa_tagstruct *t;
|
||||
struct timeval now;
|
||||
|
||||
o = pa_operation_new(s->context, s);
|
||||
assert(o);
|
||||
|
|
@ -362,6 +380,10 @@ struct pa_operation* pa_stream_get_latency(struct pa_stream *s, void (*cb)(struc
|
|||
pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY);
|
||||
pa_tagstruct_putu32(t, tag = s->context->ctag++);
|
||||
pa_tagstruct_putu32(t, s->channel);
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
pa_tagstruct_put_timeval(t, &now);
|
||||
|
||||
pa_pstream_send_tagstruct(s->context->pstream, t);
|
||||
pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, o);
|
||||
|
||||
|
|
|
|||
|
|
@ -342,7 +342,7 @@ static void request_bytes(struct playback_stream *s) {
|
|||
|
||||
if (!(l = pa_memblockq_missing(s->memblockq)))
|
||||
return;
|
||||
|
||||
|
||||
if (l <= s->requested_bytes)
|
||||
return;
|
||||
|
||||
|
|
@ -361,7 +361,7 @@ static void request_bytes(struct playback_stream *s) {
|
|||
pa_tagstruct_putu32(t, l);
|
||||
pa_pstream_send_tagstruct(s->connection->pstream, t);
|
||||
|
||||
/*pa_log(__FILE__": Requesting %u bytes\n", l);*/
|
||||
/* pa_log(__FILE__": Requesting %u bytes\n", l); */
|
||||
}
|
||||
|
||||
static void send_memblock(struct connection *c) {
|
||||
|
|
@ -541,6 +541,7 @@ static void command_create_playback_stream(struct pa_pdispatch *pd, uint32_t com
|
|||
pa_tagstruct_putu32(reply, s->index);
|
||||
assert(s->sink_input);
|
||||
pa_tagstruct_putu32(reply, s->sink_input->index);
|
||||
pa_tagstruct_putu32(reply, s->requested_bytes = pa_memblockq_missing(s->memblockq));
|
||||
pa_pstream_send_tagstruct(c->pstream, reply);
|
||||
request_bytes(s);
|
||||
}
|
||||
|
|
@ -809,10 +810,12 @@ static void command_get_playback_latency(struct pa_pdispatch *pd, uint32_t comma
|
|||
struct connection *c = userdata;
|
||||
struct pa_tagstruct *reply;
|
||||
struct playback_stream *s;
|
||||
struct timeval tv, now;
|
||||
uint32_t index;
|
||||
assert(c && t);
|
||||
|
||||
if (pa_tagstruct_getu32(t, &index) < 0 ||
|
||||
pa_tagstruct_get_timeval(t, &tv) < 0 ||
|
||||
!pa_tagstruct_eof(t)) {
|
||||
protocol_error(c);
|
||||
return;
|
||||
|
|
@ -836,6 +839,9 @@ static void command_get_playback_latency(struct pa_pdispatch *pd, uint32_t comma
|
|||
pa_tagstruct_putu32(reply, pa_sink_get_latency(s->sink_input->sink));
|
||||
pa_tagstruct_put_boolean(reply, pa_memblockq_is_readable(s->memblockq));
|
||||
pa_tagstruct_putu32(reply, pa_memblockq_get_length(s->memblockq));
|
||||
pa_tagstruct_put_timeval(reply, &tv);
|
||||
gettimeofday(&now, NULL);
|
||||
pa_tagstruct_put_timeval(reply, &now);
|
||||
pa_pstream_send_tagstruct(c->pstream, reply);
|
||||
}
|
||||
|
||||
|
|
@ -1439,7 +1445,7 @@ static void pstream_memblock_callback(struct pa_pstream *p, uint32_t channel, ui
|
|||
/*pa_log(__FILE__": after_recv: %u\n", pa_memblockq_get_length(p->memblockq));*/
|
||||
|
||||
pa_sink_notify(p->sink_input->sink);
|
||||
/*pa_log(__FILE__": Recieved %u bytes.\n", chunk->length);*/
|
||||
/* pa_log(__FILE__": Recieved %u bytes.\n", chunk->length); */
|
||||
|
||||
} else {
|
||||
struct upload_stream *u = (struct upload_stream*) stream;
|
||||
|
|
|
|||
|
|
@ -215,7 +215,7 @@ void pa_pstream_send_packet(struct pa_pstream*p, struct pa_packet *packet) {
|
|||
struct item_info *i;
|
||||
assert(p && packet);
|
||||
|
||||
/*pa_log(__FILE__": push-packet %p\n", packet);*/
|
||||
/* pa_log(__FILE__": push-packet %p\n", packet); */
|
||||
|
||||
i = pa_xmalloc(sizeof(struct item_info));
|
||||
i->type = PA_PSTREAM_ITEM_PACKET;
|
||||
|
|
@ -228,6 +228,8 @@ void pa_pstream_send_packet(struct pa_pstream*p, struct pa_packet *packet) {
|
|||
void pa_pstream_send_memblock(struct pa_pstream*p, uint32_t channel, uint32_t delta, const struct pa_memchunk *chunk) {
|
||||
struct item_info *i;
|
||||
assert(p && channel != (uint32_t) -1 && chunk);
|
||||
|
||||
/* pa_log(__FILE__": push-memblock %p\n", chunk); */
|
||||
|
||||
i = pa_xmalloc(sizeof(struct item_info));
|
||||
i->type = PA_PSTREAM_ITEM_MEMBLOCK;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@
|
|||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <samplerate.h>
|
||||
|
|
@ -31,6 +30,7 @@
|
|||
#include "resampler.h"
|
||||
#include "sconv.h"
|
||||
#include "xmalloc.h"
|
||||
#include "log.h"
|
||||
|
||||
struct pa_resampler {
|
||||
struct pa_sample_spec i_ss, o_ss;
|
||||
|
|
@ -120,6 +120,8 @@ void pa_resampler_run(struct pa_resampler *r, const struct pa_memchunk *in, stru
|
|||
/* How many input samples? */
|
||||
ins = in->length/r->i_sz;
|
||||
|
||||
/* pa_log("%u / %u = %u\n", in->length, r->i_sz, ins); */
|
||||
|
||||
/* How much space for output samples? */
|
||||
if (r->src_state)
|
||||
ons = (ins*r->o_ss.rate/r->i_ss.rate)+1024;
|
||||
|
|
@ -137,6 +139,9 @@ void pa_resampler_run(struct pa_resampler *r, const struct pa_memchunk *in, stru
|
|||
eff_ins = ins;
|
||||
eff_ons = ons;
|
||||
}
|
||||
|
||||
/* pa_log("eff_ins = %u \n", eff_ins); */
|
||||
|
||||
|
||||
out->memblock = pa_memblock_new(out->length = (ons*r->o_sz), r->memblock_stat);
|
||||
out->index = 0;
|
||||
|
|
@ -145,7 +150,9 @@ void pa_resampler_run(struct pa_resampler *r, const struct pa_memchunk *in, stru
|
|||
if (r->i_alloc < eff_ins)
|
||||
r->i_buf = pa_xrealloc(r->i_buf, sizeof(float) * (r->i_alloc = eff_ins));
|
||||
assert(r->i_buf);
|
||||
|
||||
|
||||
/* pa_log("eff_ins = %u \n", eff_ins); */
|
||||
|
||||
r->to_float32_func(eff_ins, (uint8_t*) in->memblock->data+in->index, i_nchannels, r->i_buf);
|
||||
|
||||
if (r->src_state) {
|
||||
|
|
@ -179,6 +186,13 @@ void pa_resampler_run(struct pa_resampler *r, const struct pa_memchunk *in, stru
|
|||
} else
|
||||
cbuf = r->i_buf;
|
||||
|
||||
r->from_float32_func(eff_ons, cbuf, (uint8_t*)out->memblock->data+out->index, o_nchannels);
|
||||
if (eff_ons)
|
||||
r->from_float32_func(eff_ons, cbuf, (uint8_t*)out->memblock->data+out->index, o_nchannels);
|
||||
out->length = ons*r->o_sz;
|
||||
|
||||
|
||||
if (!out->length) {
|
||||
pa_memblock_unref(out->memblock);
|
||||
out->memblock = NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include "endianmacros.h"
|
||||
#include "sconv.h"
|
||||
#include "log.h"
|
||||
|
||||
#ifndef INT16_FROM
|
||||
#define INT16_FROM INT16_FROM_LE
|
||||
|
|
@ -61,6 +62,9 @@ void pa_sconv_s16le_to_float32(unsigned n, const void *a, unsigned an, float *b)
|
|||
|
||||
void pa_sconv_s16le_from_float32(unsigned n, const float *a, void *b, unsigned bn) {
|
||||
int16_t *cb = b;
|
||||
|
||||
/* pa_log("%u %p %p %u\n", n, a, b, bn); */
|
||||
|
||||
assert(n && a && b && bn);
|
||||
|
||||
for (; n > 0; n--) {
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ int pa_sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) {
|
|||
if (!i->resampler)
|
||||
return i->peek(i, chunk);
|
||||
|
||||
if (!i->resampled_chunk.memblock) {
|
||||
while (!i->resampled_chunk.memblock) {
|
||||
struct pa_memchunk tchunk;
|
||||
size_t l;
|
||||
int ret;
|
||||
|
|
@ -141,10 +141,11 @@ int pa_sink_input_peek(struct pa_sink_input *i, struct pa_memchunk *chunk) {
|
|||
|
||||
l = pa_resampler_request(i->resampler, CONVERT_BUFFER_LENGTH);
|
||||
|
||||
if (tchunk.length > l)
|
||||
tchunk.length = l;
|
||||
if (l > tchunk.length)
|
||||
l = tchunk.length;
|
||||
|
||||
i->drop(i, &tchunk, tchunk.length);
|
||||
i->drop(i, &tchunk, l);
|
||||
tchunk.length = l;
|
||||
|
||||
pa_resampler_run(i->resampler, &tchunk, &i->resampled_chunk);
|
||||
pa_memblock_unref(tchunk.memblock);
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ enum tags {
|
|||
TAG_ARBITRARY = 'x',
|
||||
TAG_BOOLEAN_TRUE = '1',
|
||||
TAG_BOOLEAN_FALSE = '0',
|
||||
TAG_TIMEVAL = 'T',
|
||||
};
|
||||
|
||||
struct pa_tagstruct {
|
||||
|
|
@ -145,6 +146,15 @@ void pa_tagstruct_put_boolean(struct pa_tagstruct*t, int b) {
|
|||
t->length += 1;
|
||||
}
|
||||
|
||||
void pa_tagstruct_put_timeval(struct pa_tagstruct*t, const struct timeval *tv) {
|
||||
assert(t);
|
||||
extend(t, 9);
|
||||
t->data[t->length] = TAG_TIMEVAL;
|
||||
*((uint32_t*) (t->data+t->length+1)) = htonl(tv->tv_sec);
|
||||
*((uint32_t*) (t->data+t->length+5)) = htonl(tv->tv_usec);
|
||||
t->length += 9;
|
||||
}
|
||||
|
||||
int pa_tagstruct_gets(struct pa_tagstruct*t, const char **s) {
|
||||
int error = 0;
|
||||
size_t n;
|
||||
|
|
@ -263,4 +273,18 @@ int pa_tagstruct_get_boolean(struct pa_tagstruct*t, int *b) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int pa_tagstruct_get_timeval(struct pa_tagstruct*t, struct timeval *tv) {
|
||||
|
||||
if (t->rindex+9 > t->length)
|
||||
return -1;
|
||||
|
||||
if (t->data[t->rindex] != TAG_TIMEVAL)
|
||||
return -1;
|
||||
|
||||
tv->tv_sec = ntohl(*((uint32_t*) (t->data+t->rindex+1)));
|
||||
tv->tv_usec = ntohl(*((uint32_t*) (t->data+t->rindex+5)));
|
||||
t->rindex += 9;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ void pa_tagstruct_putu8(struct pa_tagstruct*t, uint8_t c);
|
|||
void pa_tagstruct_put_sample_spec(struct pa_tagstruct *t, const struct pa_sample_spec *ss);
|
||||
void pa_tagstruct_put_arbitrary(struct pa_tagstruct*t, const void *p, size_t length);
|
||||
void pa_tagstruct_put_boolean(struct pa_tagstruct*t, int b);
|
||||
void pa_tagstruct_put_timeval(struct pa_tagstruct*t, const struct timeval *tv);
|
||||
|
||||
int pa_tagstruct_gets(struct pa_tagstruct*t, const char **s);
|
||||
int pa_tagstruct_getu32(struct pa_tagstruct*t, uint32_t *i);
|
||||
|
|
@ -46,6 +47,7 @@ int pa_tagstruct_getu8(struct pa_tagstruct*t, uint8_t *c);
|
|||
int pa_tagstruct_get_sample_spec(struct pa_tagstruct *t, struct pa_sample_spec *ss);
|
||||
int pa_tagstruct_get_arbitrary(struct pa_tagstruct *t, const void **p, size_t length);
|
||||
int pa_tagstruct_get_boolean(struct pa_tagstruct *t, int *b);
|
||||
int pa_tagstruct_get_timeval(struct pa_tagstruct*t, struct timeval *tv);
|
||||
|
||||
int pa_tagstruct_eof(struct pa_tagstruct*t);
|
||||
const uint8_t* pa_tagstruct_data(struct pa_tagstruct*t, size_t *l);
|
||||
|
|
|
|||
52
polyp/util.c
52
polyp/util.c
|
|
@ -221,26 +221,52 @@ char *pa_get_host_name(char *s, size_t l) {
|
|||
return s;
|
||||
}
|
||||
|
||||
uint32_t pa_age(struct timeval *tv) {
|
||||
struct timeval now;
|
||||
uint32_t r;
|
||||
assert(tv);
|
||||
pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) {
|
||||
pa_usec_t r;
|
||||
assert(a && b);
|
||||
|
||||
if (tv->tv_sec == 0)
|
||||
return 0;
|
||||
if (pa_timeval_cmp(a, b) < 0) {
|
||||
const struct timeval *c;
|
||||
c = a;
|
||||
a = b;
|
||||
b = c;
|
||||
}
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
|
||||
r = (now.tv_sec-tv->tv_sec) * 1000000;
|
||||
r = (a->tv_sec - b->tv_sec)* 1000000;
|
||||
|
||||
if (now.tv_usec >= tv->tv_usec)
|
||||
r += now.tv_usec - tv->tv_usec;
|
||||
else
|
||||
r -= tv->tv_usec - now.tv_usec;
|
||||
if (a->tv_usec > b->tv_usec)
|
||||
r += (a->tv_usec - b->tv_usec);
|
||||
else if (a->tv_usec < b->tv_usec)
|
||||
r -= (b->tv_usec - a->tv_usec);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int pa_timeval_cmp(const struct timeval *a, const struct timeval *b) {
|
||||
assert(a && b);
|
||||
|
||||
if (a->tv_sec < b->tv_sec)
|
||||
return -1;
|
||||
|
||||
if (a->tv_sec > b->tv_sec)
|
||||
return 1;
|
||||
|
||||
if (a->tv_usec < b->tv_usec)
|
||||
return -1;
|
||||
|
||||
if (a->tv_usec > b->tv_usec)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
pa_usec_t pa_age(const struct timeval *tv) {
|
||||
struct timeval now;
|
||||
assert(tv);
|
||||
gettimeofday(&now, NULL);
|
||||
return pa_timeval_diff(&now, tv);
|
||||
}
|
||||
|
||||
#define NICE_LEVEL (-15)
|
||||
|
||||
void pa_raise_priority(void) {
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include <stdarg.h>
|
||||
|
||||
#include "gcc-printf.h"
|
||||
#include "sample.h"
|
||||
|
||||
void pa_make_nonblock_fd(int fd);
|
||||
|
||||
|
|
@ -43,7 +44,9 @@ char *pa_vsprintf_malloc(const char *format, va_list ap);
|
|||
char *pa_get_user_name(char *s, size_t l);
|
||||
char *pa_get_host_name(char *s, size_t l);
|
||||
|
||||
uint32_t pa_age(struct timeval *tv);
|
||||
pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b);
|
||||
int pa_timeval_cmp(const struct timeval *a, const struct timeval *b);
|
||||
pa_usec_t pa_age(const struct timeval *tv);
|
||||
|
||||
void pa_raise_priority(void);
|
||||
void pa_reset_priority(void);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue