diff options
| author | Lennart Poettering <lennart@poettering.net> | 2006-05-25 23:20:28 +0000 | 
|---|---|---|
| committer | Lennart Poettering <lennart@poettering.net> | 2006-05-25 23:20:28 +0000 | 
| commit | 7d975345a555fc20e5019307c7dc01545552e42d (patch) | |
| tree | 738c6340193a144b5b6d96915210fa355b851d1f | |
| parent | b754d5095e8c1bbf41e7c0147dfb2328145a2c83 (diff) | |
* add new API function pa_stream_get_buffer_attr().
* 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
| -rw-r--r-- | configure.ac | 2 | ||||
| -rw-r--r-- | src/polyp/internal.h | 1 | ||||
| -rw-r--r-- | src/polyp/stream.c | 47 | ||||
| -rw-r--r-- | src/polyp/stream.h | 5 | ||||
| -rw-r--r-- | src/polypcore/memblockq.c | 12 | ||||
| -rw-r--r-- | src/polypcore/memblockq.h | 6 | ||||
| -rw-r--r-- | src/polypcore/protocol-native.c | 21 | ||||
| -rw-r--r-- | src/utils/pacat.c | 20 | 
8 files changed, 109 insertions, 5 deletions
diff --git a/configure.ac b/configure.ac index 157c01a4..7859d33f 100644 --- a/configure.ac +++ b/configure.ac @@ -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]) diff --git a/src/polyp/internal.h b/src/polyp/internal.h index 80c28616..d88a1e5b 100644 --- a/src/polyp/internal.h +++ b/src/polyp/internal.h @@ -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; diff --git a/src/polyp/stream.c b/src/polyp/stream.c index e41c588e..17884ed3 100644 --- a/src/polyp/stream.c +++ b/src/polyp/stream.c @@ -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; +} diff --git a/src/polyp/stream.h b/src/polyp/stream.h index ad77d938..d1f558ae 100644 --- a/src/polyp/stream.h +++ b/src/polyp/stream.h @@ -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 diff --git a/src/polypcore/memblockq.c b/src/polypcore/memblockq.c index caacd96f..8ed358fa 100644 --- a/src/polypcore/memblockq.c +++ b/src/polypcore/memblockq.c @@ -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; +} diff --git a/src/polypcore/memblockq.h b/src/polypcore/memblockq.h index 302a5366..74fb00ee 100644 --- a/src/polypcore/memblockq.h +++ b/src/polypcore/memblockq.h @@ -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 diff --git a/src/polypcore/protocol-native.c b/src/polypcore/protocol-native.c index a300c45d..7ab11209 100644 --- a/src/polypcore/protocol-native.c +++ b/src/polypcore/protocol-native.c @@ -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"); diff --git a/src/utils/pacat.c b/src/utils/pacat.c index b1f5bf59..83c3d3ca 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -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:  | 
