From f05a4ac806d8d44ab1377ea2069abb1da7ab9d16 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 12 Sep 2004 13:14:49 +0000 Subject: [PATCH] extend pa_usec_t to 64 bit git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@192 fefdeb5f-60dc-0310-8127-8f9354f1896f --- doc/todo | 4 +--- polyp/cli-text.c | 8 ++++---- polyp/main.c | 2 ++ polyp/module-alsa-sink.c | 2 +- polyp/module-oss-mmap.c | 2 +- polyp/module-oss.c | 2 +- polyp/pacat.c | 2 +- polyp/polyplib-introspect.c | 8 ++++---- polyp/polyplib-stream.c | 4 ++-- polyp/protocol-esound.c | 6 +++--- polyp/protocol-native.c | 16 ++++++++-------- polyp/protocol-simple.c | 2 +- polyp/sample.c | 4 ++-- polyp/sample.h | 4 ++-- polyp/sink-input.h | 2 +- polyp/sink.h | 2 +- polyp/tagstruct.c | 26 ++++++++++++++++++++++++++ polyp/tagstruct.h | 2 ++ polyp/util.c | 6 +++--- 19 files changed, 66 insertions(+), 38 deletions(-) diff --git a/doc/todo b/doc/todo index c9be66a..af54c69 100644 --- a/doc/todo +++ b/doc/todo @@ -13,13 +13,11 @@ - 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 -- extend pa_usec_t to 64 bit -- make use of network latency in all apps - fix or work around libtool bug - merge pa_context_connect_* +- input latency ** later *** - xmlrpc/http diff --git a/polyp/cli-text.c b/polyp/cli-text.c index 18a99cf..1d6711d 100644 --- a/polyp/cli-text.c +++ b/polyp/cli-text.c @@ -93,12 +93,12 @@ char *pa_sink_list_to_string(struct pa_core *c) { assert(sink->monitor_source); pa_strbuf_printf( s, - " %c index: %u\n\tname: <%s>\n\tvolume: <0x%04x> (%0.2fdB)\n\tlatency: <%u usec>\n\tmonitor_source: <%u>\n\tsample_spec: <%s>\n", + " %c index: %u\n\tname: <%s>\n\tvolume: <0x%04x> (%0.2fdB)\n\tlatency: <%f usec>\n\tmonitor_source: <%u>\n\tsample_spec: <%s>\n", c->default_sink_name && !strcmp(sink->name, c->default_sink_name) ? '*' : ' ', sink->index, sink->name, (unsigned) sink->volume, pa_volume_to_dB(sink->volume), - pa_sink_get_latency(sink), + (float) pa_sink_get_latency(sink), sink->monitor_source->index, ss); @@ -189,13 +189,13 @@ char *pa_sink_input_list_to_string(struct pa_core *c) { pa_sample_spec_snprint(ss, sizeof(ss), &i->sample_spec); assert(i->sink); pa_strbuf_printf( - s, " index: %u\n\tname: <%s>\n\tsink: <%u>\n\tvolume: <0x%04x> (%0.2fdB)\n\tlatency: <%u usec>\n\tsample_spec: <%s>\n", + s, " index: %u\n\tname: <%s>\n\tsink: <%u>\n\tvolume: <0x%04x> (%0.2fdB)\n\tlatency: <%f usec>\n\tsample_spec: <%s>\n", i->index, i->name, i->sink->index, (unsigned) i->volume, pa_volume_to_dB(i->volume), - pa_sink_input_get_latency(i), + (float) pa_sink_input_get_latency(i), ss); if (i->owner) diff --git a/polyp/main.c b/polyp/main.c index 0218f39..a2b3d4c 100644 --- a/polyp/main.c +++ b/polyp/main.c @@ -188,6 +188,8 @@ int main(int argc, char *argv[]) { lt_dlsetsearchpath(DLSEARCHPATH); #endif + pa_log(__FILE__": sizeof(pa_usec_t) = %u\n", sizeof(pa_usec_t)); + mainloop = pa_mainloop_new(); assert(mainloop); diff --git a/polyp/module-alsa-sink.c b/polyp/module-alsa-sink.c index 73c46ea..95bb81f 100644 --- a/polyp/module-alsa-sink.c +++ b/polyp/module-alsa-sink.c @@ -143,7 +143,7 @@ static void io_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int fd, do_write(u); } -static uint32_t sink_get_latency_cb(struct pa_sink *s) { +static pa_usec_t sink_get_latency_cb(struct pa_sink *s) { struct userdata *u = s->userdata; snd_pcm_sframes_t frames; assert(s && u && u->sink); diff --git a/polyp/module-oss-mmap.c b/polyp/module-oss-mmap.c index 4ffc56e..8e16521 100644 --- a/polyp/module-oss-mmap.c +++ b/polyp/module-oss-mmap.c @@ -210,7 +210,7 @@ static void io_callback(struct pa_mainloop_api *m, struct pa_io_event *e, int fd do_write(u); } -static uint32_t sink_get_latency_cb(struct pa_sink *s) { +static pa_usec_t sink_get_latency_cb(struct pa_sink *s) { struct userdata *u = s->userdata; assert(s && u); diff --git a/polyp/module-oss.c b/polyp/module-oss.c index 75d72e5..51cc42e 100644 --- a/polyp/module-oss.c +++ b/polyp/module-oss.c @@ -161,7 +161,7 @@ static void io_callback(struct pa_iochannel *io, void*userdata) { do_read(u); } -static uint32_t sink_get_latency_cb(struct pa_sink *s) { +static pa_usec_t sink_get_latency_cb(struct pa_sink *s) { int arg; struct userdata *u = s->userdata; assert(s && u && u->sink); diff --git a/polyp/pacat.c b/polyp/pacat.c index 0ad5fa5..ed95c2c 100644 --- a/polyp/pacat.c +++ b/polyp/pacat.c @@ -286,7 +286,7 @@ static void stream_get_latency_callback(struct pa_stream *s, const struct pa_lat return; } - fprintf(stderr, "Current latency is %u usecs.\n", i->buffer_usec+i->sink_usec); + fprintf(stderr, "Current latency is %f usecs.\n", (float) (i->buffer_usec+i->sink_usec+i->transport_usec)); } /* Someone requested that the latency is shown */ diff --git a/polyp/polyplib-introspect.c b/polyp/polyplib-introspect.c index 2baeb54..e742c2d 100644 --- a/polyp/polyplib-introspect.c +++ b/polyp/polyplib-introspect.c @@ -130,7 +130,7 @@ static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t com pa_tagstruct_getu32(t, &i.volume) < 0 || pa_tagstruct_getu32(t, &i.monitor_source) < 0 || pa_tagstruct_gets(t, &i.monitor_source_name) < 0 || - pa_tagstruct_getu32(t, &i.latency) < 0) { + pa_tagstruct_get_usec(t, &i.latency) < 0) { pa_context_fail(o->context, PA_ERROR_PROTOCOL); goto finish; } @@ -446,8 +446,8 @@ static void context_get_sink_input_info_callback(struct pa_pdispatch *pd, uint32 pa_tagstruct_getu32(t, &i.sink) < 0 || pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || pa_tagstruct_getu32(t, &i.volume) < 0 || - pa_tagstruct_getu32(t, &i.buffer_usec) < 0 || - pa_tagstruct_getu32(t, &i.sink_usec) < 0) { + pa_tagstruct_get_usec(t, &i.buffer_usec) < 0 || + pa_tagstruct_get_usec(t, &i.sink_usec) < 0) { pa_context_fail(o->context, PA_ERROR_PROTOCOL); goto finish; } @@ -648,7 +648,7 @@ static void context_get_sample_info_callback(struct pa_pdispatch *pd, uint32_t c 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_usec(t, &i.duration) < 0 || pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 || pa_tagstruct_getu32(t, &i.bytes) < 0) { pa_context_fail(o->context, PA_ERROR_PROTOCOL); diff --git a/polyp/polyplib-stream.c b/polyp/polyplib-stream.c index e128a77..98610d6 100644 --- a/polyp/polyplib-stream.c +++ b/polyp/polyplib-stream.c @@ -333,8 +333,8 @@ static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t comman if (pa_context_handle_error(o->context, command, t) < 0) goto finish; - } else if (pa_tagstruct_getu32(t, &i.buffer_usec) < 0 || - pa_tagstruct_getu32(t, &i.sink_usec) < 0 || + } else if (pa_tagstruct_get_usec(t, &i.buffer_usec) < 0 || + pa_tagstruct_get_usec(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 || diff --git a/polyp/protocol-esound.c b/polyp/protocol-esound.c index 3f87d4d..178ba00 100644 --- a/polyp/protocol-esound.c +++ b/polyp/protocol-esound.c @@ -106,7 +106,7 @@ typedef struct proto_handler { static void sink_input_drop_cb(struct pa_sink_input *i, const struct pa_memchunk *chunk, size_t length); static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk); static void sink_input_kill_cb(struct pa_sink_input *i); -static uint32_t sink_input_get_latency_cb(struct pa_sink_input *i); +static pa_usec_t sink_input_get_latency_cb(struct pa_sink_input *i); static void source_output_push_cb(struct pa_source_output *o, const struct pa_memchunk *chunk); static void source_output_kill_cb(struct pa_source_output *o); @@ -385,7 +385,7 @@ static int esd_proto_get_latency(struct connection *c, esd_proto_t request, cons if (!(sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1))) latency = 0; else { - float usec = pa_sink_get_latency(sink); + double usec = pa_sink_get_latency(sink); usec += PLAYBACK_BUFFER_SECONDS*1000000; /* A better estimation would be a good idea! */ latency = (int) ((usec*44100)/1000000); } @@ -914,7 +914,7 @@ static void sink_input_kill_cb(struct pa_sink_input *i) { } -static uint32_t sink_input_get_latency_cb(struct pa_sink_input *i) { +static pa_usec_t sink_input_get_latency_cb(struct pa_sink_input *i) { struct connection*c = i->userdata; assert(i && c); return pa_bytes_to_usec(pa_memblockq_get_length(c->input_memblockq), &c->sink_input->sample_spec); diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index 058ba9c..3056f7c 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -110,7 +110,7 @@ struct pa_protocol_native { static int sink_input_peek_cb(struct pa_sink_input *i, struct pa_memchunk *chunk); static void sink_input_drop_cb(struct pa_sink_input *i, const struct pa_memchunk *chunk, size_t length); static void sink_input_kill_cb(struct pa_sink_input *i); -static uint32_t sink_input_get_latency_cb(struct pa_sink_input *i); +static pa_usec_t sink_input_get_latency_cb(struct pa_sink_input *i); static void request_bytes(struct playback_stream*s); @@ -455,7 +455,7 @@ static void sink_input_kill_cb(struct pa_sink_input *i) { playback_stream_free((struct playback_stream *) i->userdata); } -static uint32_t sink_input_get_latency_cb(struct pa_sink_input *i) { +static pa_usec_t sink_input_get_latency_cb(struct pa_sink_input *i) { struct playback_stream *s; assert(i && i->userdata); s = i->userdata; @@ -835,8 +835,8 @@ static void command_get_playback_latency(struct pa_pdispatch *pd, uint32_t comma assert(reply); pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); pa_tagstruct_putu32(reply, tag); - pa_tagstruct_putu32(reply, pa_sink_input_get_latency(s->sink_input)); - pa_tagstruct_putu32(reply, pa_sink_get_latency(s->sink_input->sink)); + pa_tagstruct_put_usec(reply, pa_sink_input_get_latency(s->sink_input)); + pa_tagstruct_put_usec(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); @@ -994,7 +994,7 @@ static void sink_fill_tagstruct(struct pa_tagstruct *t, struct pa_sink *sink) { pa_tagstruct_putu32(t, sink->volume); pa_tagstruct_putu32(t, sink->monitor_source->index); pa_tagstruct_puts(t, sink->monitor_source->name); - pa_tagstruct_putu32(t, pa_sink_get_latency(sink)); + pa_tagstruct_put_usec(t, pa_sink_get_latency(sink)); } static void source_fill_tagstruct(struct pa_tagstruct *t, struct pa_source *source) { @@ -1034,8 +1034,8 @@ static void sink_input_fill_tagstruct(struct pa_tagstruct *t, struct pa_sink_inp pa_tagstruct_putu32(t, s->sink->index); pa_tagstruct_put_sample_spec(t, &s->sample_spec); pa_tagstruct_putu32(t, s->volume); - pa_tagstruct_putu32(t, pa_sink_input_get_latency(s)); - pa_tagstruct_putu32(t, pa_sink_get_latency(s->sink)); + pa_tagstruct_put_usec(t, pa_sink_input_get_latency(s)); + pa_tagstruct_put_usec(t, pa_sink_get_latency(s->sink)); } static void source_output_fill_tagstruct(struct pa_tagstruct *t, struct pa_source_output *s) { @@ -1053,7 +1053,7 @@ static void scache_fill_tagstruct(struct pa_tagstruct *t, struct pa_scache_entry 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_usec(t, pa_bytes_to_usec(e->memchunk.length, &e->sample_spec)); pa_tagstruct_put_sample_spec(t, &e->sample_spec); pa_tagstruct_putu32(t, e->memchunk.length); } diff --git a/polyp/protocol-simple.c b/polyp/protocol-simple.c index f624046..00db0aa 100644 --- a/polyp/protocol-simple.c +++ b/polyp/protocol-simple.c @@ -220,7 +220,7 @@ static void sink_input_kill_cb(struct pa_sink_input *i) { } -static uint32_t sink_input_get_latency_cb(struct pa_sink_input *i) { +static pa_usec_t sink_input_get_latency_cb(struct pa_sink_input *i) { struct connection*c = i->userdata; assert(i && c); return pa_bytes_to_usec(pa_memblockq_get_length(c->input_memblockq), &c->sink_input->sample_spec); diff --git a/polyp/sample.c b/polyp/sample.c index 747acf1..dfe98e3 100644 --- a/polyp/sample.c +++ b/polyp/sample.c @@ -59,10 +59,10 @@ size_t pa_bytes_per_second(const struct pa_sample_spec *spec) { return spec->rate*pa_frame_size(spec); } -uint32_t pa_bytes_to_usec(size_t length, const struct pa_sample_spec *spec) { +pa_usec_t pa_bytes_to_usec(size_t length, const struct pa_sample_spec *spec) { assert(spec); - return (uint32_t) (((double) length/pa_frame_size(spec)*1000000)/spec->rate); + return (pa_usec_t) (((double) length/pa_frame_size(spec)*1000000)/spec->rate); } int pa_sample_spec_valid(const struct pa_sample_spec *spec) { diff --git a/polyp/sample.h b/polyp/sample.h index 0141a7c..1e42a26 100644 --- a/polyp/sample.h +++ b/polyp/sample.h @@ -67,8 +67,8 @@ struct pa_sample_spec { uint8_t channels; /**< Audio channels. (1 for mono, 2 for stereo, ...) */ }; -/** Type for usec specifications */ -typedef uint32_t pa_usec_t; +/** Type for usec specifications. May be either 32 or 64 bit, depending on the architecture */ +typedef uint64_t pa_usec_t; /** Return the amount of bytes playback of a second of audio with the speicified sample type takes */ size_t pa_bytes_per_second(const struct pa_sample_spec *spec); diff --git a/polyp/sink-input.h b/polyp/sink-input.h index df6ead6..e2478ed 100644 --- a/polyp/sink-input.h +++ b/polyp/sink-input.h @@ -46,7 +46,7 @@ struct pa_sink_input { int (*peek) (struct pa_sink_input *i, struct pa_memchunk *chunk); void (*drop) (struct pa_sink_input *i, const struct pa_memchunk *chunk, size_t length); void (*kill) (struct pa_sink_input *i); - uint32_t (*get_latency) (struct pa_sink_input *i); + pa_usec_t (*get_latency) (struct pa_sink_input *i); void *userdata; diff --git a/polyp/sink.h b/polyp/sink.h index 85addf7..881e75d 100644 --- a/polyp/sink.h +++ b/polyp/sink.h @@ -47,7 +47,7 @@ struct pa_sink { pa_volume_t volume; void (*notify)(struct pa_sink*sink); - uint32_t (*get_latency)(struct pa_sink *s); + pa_usec_t (*get_latency)(struct pa_sink *s); void *userdata; }; diff --git a/polyp/tagstruct.c b/polyp/tagstruct.c index 55132ca..52db0fe 100644 --- a/polyp/tagstruct.c +++ b/polyp/tagstruct.c @@ -39,11 +39,14 @@ enum tags { TAG_S16 = 's', TAG_U8 = 'B', TAG_S8 = 'b', + TAG_U64 = 'R', + TAG_S64 = 'r', TAG_SAMPLE_SPEC = 'a', TAG_ARBITRARY = 'x', TAG_BOOLEAN_TRUE = '1', TAG_BOOLEAN_FALSE = '0', TAG_TIMEVAL = 'T', + TAG_USEC = 'U', /* 64bit unsigned */ }; struct pa_tagstruct { @@ -155,6 +158,15 @@ void pa_tagstruct_put_timeval(struct pa_tagstruct*t, const struct timeval *tv) { t->length += 9; } +void pa_tagstruct_put_usec(struct pa_tagstruct*t, pa_usec_t u) { + assert(t); + extend(t, 9); + t->data[t->length] = TAG_USEC; + *((uint32_t*) (t->data+t->length+1)) = htonl((uint32_t) (u >> 32)); + *((uint32_t*) (t->data+t->length+5)) = htonl((uint32_t) u); + t->length += 9; +} + int pa_tagstruct_gets(struct pa_tagstruct*t, const char **s) { int error = 0; size_t n; @@ -288,3 +300,17 @@ int pa_tagstruct_get_timeval(struct pa_tagstruct*t, struct timeval *tv) { } +int pa_tagstruct_get_usec(struct pa_tagstruct*t, pa_usec_t *u) { + assert(t && u); + + if (t->rindex+9 > t->length) + return -1; + + if (t->data[t->rindex] != TAG_USEC) + return -1; + + *u = (pa_usec_t) ntohl(*((uint32_t*) (t->data+t->rindex+1))) << 32; + *u |= (pa_usec_t) ntohl(*((uint32_t*) (t->data+t->rindex+5))); + t->rindex +=9; + return 0; +} diff --git a/polyp/tagstruct.h b/polyp/tagstruct.h index 915a9a6..02df74e 100644 --- a/polyp/tagstruct.h +++ b/polyp/tagstruct.h @@ -40,6 +40,7 @@ void pa_tagstruct_put_sample_spec(struct pa_tagstruct *t, const struct pa_sample 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); +void pa_tagstruct_put_usec(struct pa_tagstruct*t, pa_usec_t u); int pa_tagstruct_gets(struct pa_tagstruct*t, const char **s); int pa_tagstruct_getu32(struct pa_tagstruct*t, uint32_t *i); @@ -48,6 +49,7 @@ int pa_tagstruct_get_sample_spec(struct pa_tagstruct *t, struct pa_sample_spec * 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_get_usec(struct pa_tagstruct*t, pa_usec_t *u); int pa_tagstruct_eof(struct pa_tagstruct*t); const uint8_t* pa_tagstruct_data(struct pa_tagstruct*t, size_t *l); diff --git a/polyp/util.c b/polyp/util.c index eeb1d19..45e1b60 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -232,12 +232,12 @@ pa_usec_t pa_timeval_diff(const struct timeval *a, const struct timeval *b) { b = c; } - r = (a->tv_sec - b->tv_sec)* 1000000; + r = ((pa_usec_t) a->tv_sec - b->tv_sec)* 1000000; if (a->tv_usec > b->tv_usec) - r += (a->tv_usec - b->tv_usec); + r += ((pa_usec_t) a->tv_usec - b->tv_usec); else if (a->tv_usec < b->tv_usec) - r -= (b->tv_usec - a->tv_usec); + r -= ((pa_usec_t) b->tv_usec - a->tv_usec); return r; } -- 2.7.4