]> code.delx.au - pulseaudio/commitdiff
* add new API function pa_stream_get_buffer_attr().
authorLennart Poettering <lennart@poettering.net>
Thu, 25 May 2006 23:20:28 +0000 (23:20 +0000)
committerLennart Poettering <lennart@poettering.net>
Thu, 25 May 2006 23:20:28 +0000 (23:20 +0000)
* modify pacat.c to make use of that new API
* extend protocol to allow transfer of the necessary information
* update protocol version accordingly

git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@976 fefdeb5f-60dc-0310-8127-8f9354f1896f

configure.ac
src/polyp/internal.h
src/polyp/stream.c
src/polyp/stream.h
src/polypcore/memblockq.c
src/polypcore/memblockq.h
src/polypcore/protocol-native.c
src/utils/pacat.c

index 157c01a4b82d038967685aeba7a7624347355576..7859d33fa5011bd6f48e39df16f455a7422aa15a 100644 (file)
@@ -34,7 +34,7 @@ AC_SUBST(PA_MAJORMINOR, "PA_MAJOR.PA_MINOR")
 AC_SUBST(PACKAGE_URL, [http://0pointer.de/lennart/projects/polypaudio/])
 
 AC_SUBST(PA_API_VERSION, 9)
-AC_SUBST(PA_PROTOCOL_VERSION, 8)
+AC_SUBST(PA_PROTOCOL_VERSION, 9)
 
 AC_SUBST(LIBPOLYP_VERSION_INFO, [0:0:0])
 AC_SUBST(LIBPOLYPCORE_VERSION_INFO, [0:0:0])
index 80c286164fec1e7b4835624e9c60402427aee15f..d88a1e5b4b373e63c0f501628ef7ed2506d346fd 100644 (file)
@@ -100,6 +100,7 @@ struct pa_stream {
 
     char *name;
     pa_buffer_attr buffer_attr;
+    int buffer_attr_from_server;
     pa_sample_spec sample_spec;
     pa_channel_map channel_map;
     pa_stream_flags_t flags;
index e41c588e583699a394363b6b444c7179fab7fb01..17884ed34ecd4c98bb1caa13ba4a6d885ec765cf 100644 (file)
@@ -84,6 +84,7 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *
     s->requested_bytes = 0;
     s->state = PA_STREAM_UNCONNECTED;
     memset(&s->buffer_attr, 0, sizeof(s->buffer_attr));
+    s->buffer_attr_from_server = 0;
 
     s->peek_memchunk.index = 0;
     s->peek_memchunk.length = 0;
@@ -401,12 +402,43 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED
 
     if (pa_tagstruct_getu32(t, &s->channel) < 0 ||
         ((s->direction != PA_STREAM_UPLOAD) && pa_tagstruct_getu32(t, &s->device_index) < 0) ||
-        ((s->direction != PA_STREAM_RECORD) && pa_tagstruct_getu32(t, &s->requested_bytes) < 0) ||
-        !pa_tagstruct_eof(t)) {
+        ((s->direction != PA_STREAM_RECORD) && pa_tagstruct_getu32(t, &s->requested_bytes) < 0)) {
         pa_context_fail(s->context, PA_ERR_PROTOCOL);
         goto finish;
     }
 
+    if (!pa_tagstruct_eof(t)) {
+        
+        if (s->direction == PA_STREAM_PLAYBACK) {
+
+            /* This is a server 0.9.0 or later */
+            if (pa_tagstruct_getu32(t, &s->buffer_attr.maxlength) < 0 ||
+                pa_tagstruct_getu32(t, &s->buffer_attr.tlength) < 0 ||
+                pa_tagstruct_getu32(t, &s->buffer_attr.prebuf) < 0 ||
+                pa_tagstruct_getu32(t, &s->buffer_attr.minreq) < 0 ||
+                !pa_tagstruct_eof(t)) {
+                pa_context_fail(s->context, PA_ERR_PROTOCOL);
+                goto finish;
+            }
+
+            s->buffer_attr_from_server = 1;
+        } else if (s->direction == PA_STREAM_RECORD) {
+            
+            /* This is a server 0.9.0 or later */
+            if (pa_tagstruct_getu32(t, &s->buffer_attr.maxlength) < 0 ||
+                pa_tagstruct_getu32(t, &s->buffer_attr.fragsize) < 0 ||
+                !pa_tagstruct_eof(t)) {
+                pa_context_fail(s->context, PA_ERR_PROTOCOL);
+                goto finish;
+            }
+
+            s->buffer_attr_from_server = 1;
+        } else {
+            pa_context_fail(s->context, PA_ERR_PROTOCOL);
+            goto finish;
+        }
+    }
+
     if (s->direction == PA_STREAM_RECORD) {
         assert(!s->record_memblockq);
         
@@ -1336,3 +1368,14 @@ const pa_channel_map* pa_stream_get_channel_map(pa_stream *s) {
 
     return &s->channel_map;
 }
+
+const pa_buffer_attr* pa_stream_get_buffer_attr(pa_stream *s) {
+    assert(s);
+    assert(s->ref >= 1);
+
+    PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
+    PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
+    PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->buffer_attr_from_server, PA_ERR_NODATA);
+
+    return &s->buffer_attr;
+}
index ad77d938348b0cf2231b58270d2ef73a58629b05..d1f558aeac7c964c1ecf3f72868831446a391459 100644 (file)
@@ -439,6 +439,11 @@ const pa_sample_spec* pa_stream_get_sample_spec(pa_stream *s);
 /** Return a pointer to the stream's channel map. \since 0.8 */
 const pa_channel_map* pa_stream_get_channel_map(pa_stream *s);
 
+/** Return the buffer metrics of the stream. Only valid after the
+ * stream has been connected successfuly and if the server is at least
+ * Polypaudio 0.9. \since 0.9.0 */
+const pa_buffer_attr* pa_stream_get_buffer_attr(pa_stream *s);
+
 PA_C_DECL_END
 
 #endif
index caacd96f0db59228981a143af45ca4ba557ebe38..8ed358fa4aa0cad2b78d1faa16090fdf1f499c94 100644 (file)
@@ -622,3 +622,15 @@ void pa_memblockq_prebuf_force(pa_memblockq *bq) {
     if (bq->state == RUNNING && bq->prebuf > 0)
         bq->state = PREBUF;
 }
+
+size_t pa_memblockq_get_maxlength(pa_memblockq *bq) {
+    assert(bq);
+
+    return bq->maxlength;
+}
+
+size_t pa_memblockq_get_prebuf(pa_memblockq *bq) {
+    assert(bq);
+
+    return bq->prebuf;
+}
index 302a536682cc7a1182e6d0a1ae6eab392250aaaf..74fb00eedcf4587a4693f96f2aa8757e71006609 100644 (file)
@@ -131,4 +131,10 @@ void pa_memblockq_prebuf_disable(pa_memblockq *bq);
 /* Force prebuf */
 void pa_memblockq_prebuf_force(pa_memblockq *bq);
 
+/* Return the maximum length of the queue in bytes */
+size_t pa_memblockq_get_maxlength(pa_memblockq *bq);
+
+/* Return the prebuffer length in bytes */
+size_t pa_memblockq_get_prebuf(pa_memblockq *bq);
+
 #endif
index a300c45df5973420f96035612abcd8944d68d5db..7ab112093a90fefa5a07750a076b5779e1a70dc2 100644 (file)
@@ -755,6 +755,16 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC
     assert(s->sink_input);
     pa_tagstruct_putu32(reply, s->sink_input->index);
     pa_tagstruct_putu32(reply, s->requested_bytes = pa_memblockq_missing(s->memblockq));
+
+    if (c->version >= 9) {
+        /* Since 0.9 we support sending the buffer metrics back to the client */
+
+        pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_maxlength(s->memblockq));
+        pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_tlength(s->memblockq));
+        pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_prebuf(s->memblockq));
+        pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_minreq(s->memblockq));
+    }
+    
     pa_pstream_send_tagstruct(c->pstream, reply);
     request_bytes(s);
 }
@@ -852,6 +862,14 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
     pa_tagstruct_putu32(reply, s->index);
     assert(s->source_output);
     pa_tagstruct_putu32(reply, s->source_output->index);
+
+    if (c->version >= 9) {
+        /* Since 0.9 we support sending the buffer metrics back to the client */
+
+        pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_maxlength(s->memblockq));
+        pa_tagstruct_putu32(reply, (uint32_t) s->fragment_size);
+    }
+    
     pa_pstream_send_tagstruct(c->pstream, reply);
 }
 
@@ -2215,7 +2233,8 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo
         c->auth_timeout_event = p->core->mainloop->time_new(p->core->mainloop, &tv, auth_timeout, c);
     } else
         c->auth_timeout_event = NULL;
-    
+
+    c->version = 8;
     c->protocol = p;
     assert(p->core);
     c->client = pa_client_new(p->core, __FILE__, "Client");
index b1f5bf59a6efa54cadff66b7f0e9837d4e8bd5ce..83c3d3cab9480a67fc73a44475eeb7bee11d3129 100644 (file)
@@ -154,8 +154,26 @@ static void stream_state_callback(pa_stream *s, void *userdata) {
             break;
 
         case PA_STREAM_READY:
-            if (verbose)
+            if (verbose) {
+                pa_buffer_attr *a;
+                
                 fprintf(stderr, "Stream successfully created.\n");
+
+                if (!(a = pa_stream_get_buffer_attr(s)))
+                    fprintf(stderr, "pa_stream_get_buffer_attr() failed: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s))));
+                else {
+
+                    if (mode == PLAYBACK)
+                        fprintf(stderr, "Buffer metrics: maxlength=%u, tlength=%u, prebuf=%u, minreq=%u\n", a->maxlength, a->tlength, a->prebuf, a->minreq);
+                    else {
+                        assert(mode == RECORD);
+                        fprintf(stderr, "Buffer metrics: maxlength=%u, fragsize=%u\n", a->maxlength, a->fragsize);
+                    }
+                    
+                }
+
+            }
+            
             break;
             
         case PA_STREAM_FAILED: