mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-29 05:40:23 -04:00
extend pa_usec_t to 64 bit
git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@192 fefdeb5f-60dc-0310-8127-8f9354f1896f
This commit is contained in:
parent
a9ca9c4a3b
commit
f05a4ac806
19 changed files with 66 additions and 38 deletions
4
doc/todo
4
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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 ||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue