summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/todo4
-rw-r--r--polyp/cli-text.c8
-rw-r--r--polyp/main.c2
-rw-r--r--polyp/module-alsa-sink.c2
-rw-r--r--polyp/module-oss-mmap.c2
-rw-r--r--polyp/module-oss.c2
-rw-r--r--polyp/pacat.c2
-rw-r--r--polyp/polyplib-introspect.c8
-rw-r--r--polyp/polyplib-stream.c4
-rw-r--r--polyp/protocol-esound.c6
-rw-r--r--polyp/protocol-native.c16
-rw-r--r--polyp/protocol-simple.c2
-rw-r--r--polyp/sample.c4
-rw-r--r--polyp/sample.h4
-rw-r--r--polyp/sink-input.h2
-rw-r--r--polyp/sink.h2
-rw-r--r--polyp/tagstruct.c26
-rw-r--r--polyp/tagstruct.h2
-rw-r--r--polyp/util.c6
19 files changed, 66 insertions, 38 deletions
diff --git a/doc/todo b/doc/todo
index c9be66ab..af54c692 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 18a99cfa..1d6711df 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 0218f396..a2b3d4c7 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 73c46ea0..95bb81f1 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 4ffc56ef..8e165218 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 75d72e50..51cc42ef 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 0ad5fa52..ed95c2ca 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 2baeb540..e742c2db 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 e128a773..98610d61 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 3f87d4d0..178ba009 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 058ba9cc..3056f7c4 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 f6240462..00db0aa0 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 747acf18..dfe98e3f 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 0141a7cd..1e42a260 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 df6ead6b..e2478ed6 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 85addf76..881e75d3 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 55132cae..52db0fe3 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 915a9a65..02df74e4 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 eeb1d192..45e1b605 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;
}