]> code.delx.au - pulseaudio/commitdiff
extend pa_usec_t to 64 bit
authorLennart Poettering <lennart@poettering.net>
Sun, 12 Sep 2004 13:14:49 +0000 (13:14 +0000)
committerLennart Poettering <lennart@poettering.net>
Sun, 12 Sep 2004 13:14:49 +0000 (13:14 +0000)
git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@192 fefdeb5f-60dc-0310-8127-8f9354f1896f

19 files changed:
doc/todo
polyp/cli-text.c
polyp/main.c
polyp/module-alsa-sink.c
polyp/module-oss-mmap.c
polyp/module-oss.c
polyp/pacat.c
polyp/polyplib-introspect.c
polyp/polyplib-stream.c
polyp/protocol-esound.c
polyp/protocol-native.c
polyp/protocol-simple.c
polyp/sample.c
polyp/sample.h
polyp/sink-input.h
polyp/sink.h
polyp/tagstruct.c
polyp/tagstruct.h
polyp/util.c

index c9be66ab5e3b718793e2ca028f90e55532916cf0..af54c6929d7feab901cef37c9e8d7faaf1ee93b1 100644 (file)
--- a/doc/todo
+++ b/doc/todo
 - 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
index 18a99cfabaad5cf1439a0a425359c650abc97b83..1d6711dfacbc59d97fb00e8e1941a4775975dcbd 100644 (file)
@@ -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)
index 0218f396c3ed29270586ffaafc9275c7858aa0e7..a2b3d4c70dab817cb5939e81118528b653d9d82b 100644 (file)
@@ -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);
 
index 73c46ea051e87f75465b0d5ba53026fd36ecf690..95bb81f18c806fa4b1d869f397c6422f62582035 100644 (file)
@@ -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);
index 4ffc56efab46839f053ea38b0401a90ad64bd63a..8e1652185216df0f21a762c42b12a93cbc010f8e 100644 (file)
@@ -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);
 
index 75d72e50db5dd05401918b0f351d588f6c11877b..51cc42ef7880c4f4a66c5b20fd230e12a00112dc 100644 (file)
@@ -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);
index 0ad5fa52580a7102b3efd134de8ab71ed8230f30..ed95c2cacaec204af0c5ce0656cda7867d8c078a 100644 (file)
@@ -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 */
index 2baeb540d78e52e41176144ce67e9bf022f5bf8d..e742c2db6d9dc4ad967f7123fae767eb9360d9f4 100644 (file)
@@ -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);
index e128a773c8fd7ae5376d5aff476ec8c5961889ea..98610d61240f3ac9ed536173462660534d8d0ac7 100644 (file)
@@ -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 ||
index 3f87d4d0906932359db604590d9732b98605c027..178ba00962fe9e9029ee64e89add850173776e46 100644 (file)
@@ -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);
index 058ba9cc5b84ffb6afcb9bdc042516515fdc504b..3056f7c4518892188ba9504e1196f118d5fa279f 100644 (file)
@@ -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);
 }
index f62404625680b51956c5a0caee9ced984be1d1be..00db0aa054936a960f649a45c25f329f1973ba14 100644 (file)
@@ -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);
index 747acf18509afc4e7c19cd33436c27d821947345..dfe98e3fd919e4b467ab0772d21f3db5e6a13207 100644 (file)
@@ -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) {
index 0141a7cd1df805a1df8a64fe1b11220f4160288f..1e42a2606217d6d90193edf025f2e1a4fd1f6a27 100644 (file)
@@ -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);
index df6ead6be44cb35d873a04995d62a0507e934264..e2478ed61850b4910a32f7348fef4eef7a530708 100644 (file)
@@ -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;
 
index 85addf763f065606b31a38f7affe035e17c14358..881e75d31d4b165d04761afa16ed49e446869aa0 100644 (file)
@@ -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;
 };
 
index 55132caee57d5329ee670a09fdef85e34a2452d2..52db0fe34a9365be259fe4c01e37800d3d0e3ef1 100644 (file)
@@ -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;
+}
index 915a9a65b42438c4a4907c2fa6cb47fbad4fcd61..02df74e4d38b89effce1182892bc2609b45ad731 100644 (file)
@@ -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);
index eeb1d1922d526aeb869e4c36a01eeaac99737f57..45e1b605fd732d3c61d243891fd1bc1cdfec7cca 100644 (file)
@@ -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;
 }