mirror of
				https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
				synced 2025-10-29 05:40:23 -04:00 
			
		
		
		
	* 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
This commit is contained in:
		
							parent
							
								
									b754d5095e
								
							
						
					
					
						commit
						7d975345a5
					
				
					 8 changed files with 109 additions and 5 deletions
				
			
		|  | @ -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]) | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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; | ||||
| } | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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; | ||||
| } | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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); | ||||
| } | ||||
| 
 | ||||
|  | @ -2216,6 +2234,7 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo | |||
|     } else | ||||
|         c->auth_timeout_event = NULL; | ||||
| 
 | ||||
|     c->version = 8; | ||||
|     c->protocol = p; | ||||
|     assert(p->core); | ||||
|     c->client = pa_client_new(p->core, __FILE__, "Client"); | ||||
|  |  | |||
|  | @ -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: | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lennart Poettering
						Lennart Poettering