diff options
| -rw-r--r-- | doc/todo | 4 | ||||
| -rw-r--r-- | polyp/cli-text.c | 8 | ||||
| -rw-r--r-- | polyp/main.c | 2 | ||||
| -rw-r--r-- | polyp/module-alsa-sink.c | 2 | ||||
| -rw-r--r-- | polyp/module-oss-mmap.c | 2 | ||||
| -rw-r--r-- | polyp/module-oss.c | 2 | ||||
| -rw-r--r-- | polyp/pacat.c | 2 | ||||
| -rw-r--r-- | polyp/polyplib-introspect.c | 8 | ||||
| -rw-r--r-- | polyp/polyplib-stream.c | 4 | ||||
| -rw-r--r-- | polyp/protocol-esound.c | 6 | ||||
| -rw-r--r-- | polyp/protocol-native.c | 16 | ||||
| -rw-r--r-- | polyp/protocol-simple.c | 2 | ||||
| -rw-r--r-- | polyp/sample.c | 4 | ||||
| -rw-r--r-- | polyp/sample.h | 4 | ||||
| -rw-r--r-- | polyp/sink-input.h | 2 | ||||
| -rw-r--r-- | polyp/sink.h | 2 | ||||
| -rw-r--r-- | polyp/tagstruct.c | 26 | ||||
| -rw-r--r-- | polyp/tagstruct.h | 2 | ||||
| -rw-r--r-- | polyp/util.c | 6 | 
19 files changed, 66 insertions, 38 deletions
@@ -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;  }  | 
