mirror of
				https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
				synced 2025-10-29 05:40:23 -04:00 
			
		
		
		
	implement get_latency native command
git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@72 fefdeb5f-60dc-0310-8127-8f9354f1896f
This commit is contained in:
		
							parent
							
								
									d8f1300661
								
							
						
					
					
						commit
						710233bbf6
					
				
					 7 changed files with 125 additions and 7 deletions
				
			
		
							
								
								
									
										20
									
								
								src/pacat.c
									
										
									
									
									
								
							
							
						
						
									
										20
									
								
								src/pacat.c
									
										
									
									
									
								
							|  | @ -221,6 +221,25 @@ static void exit_signal_callback(void *id, int sig, void *userdata) { | |||
|      | ||||
| } | ||||
| 
 | ||||
| static void stream_get_latency_callback(struct pa_stream *s, uint32_t latency, void *userdata) { | ||||
|     assert(s); | ||||
| 
 | ||||
|     if (latency == (uint32_t) -1) { | ||||
|         fprintf(stderr, "Failed to get latency: %s\n", strerror(errno)); | ||||
|         quit(1); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     fprintf(stderr, "Current latency is %u usecs.\n", latency); | ||||
| } | ||||
| 
 | ||||
| static void sigusr1_signal_callback(void *id, int sig, void *userdata) { | ||||
|     if (mode == PLAYBACK) { | ||||
|         fprintf(stderr, "Got SIGUSR1, requesting latency.\n"); | ||||
|         pa_stream_get_latency(stream, stream_get_latency_callback, NULL); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| int main(int argc, char *argv[]) { | ||||
|     struct pa_mainloop* m = NULL; | ||||
|     int ret = 1, r; | ||||
|  | @ -246,6 +265,7 @@ int main(int argc, char *argv[]) { | |||
|     r = pa_signal_init(mainloop_api); | ||||
|     assert(r == 0); | ||||
|     pa_signal_register(SIGINT, exit_signal_callback, NULL); | ||||
|     pa_signal_register(SIGUSR1, sigusr1_signal_callback, NULL); | ||||
|     signal(SIGPIPE, SIG_IGN); | ||||
|      | ||||
|     if (!(stdio_source = mainloop_api->source_io(mainloop_api, | ||||
|  |  | |||
|  | @ -4,6 +4,8 @@ | |||
| #include "pdispatch.h" | ||||
| #include "protocol-native-spec.h" | ||||
| 
 | ||||
| #ifdef DEBUG_OPCODES | ||||
| 
 | ||||
| static const char *command_names[PA_COMMAND_MAX] = { | ||||
|     [PA_COMMAND_ERROR] = "ERROR", | ||||
|     [PA_COMMAND_TIMEOUT] = "TIMEOUT", | ||||
|  | @ -19,8 +21,14 @@ static const char *command_names[PA_COMMAND_MAX] = { | |||
|     [PA_COMMAND_LOOKUP_SINK] = "LOOKUP_SINK", | ||||
|     [PA_COMMAND_LOOKUP_SOURCE] = "LOOKUP_SOURCE", | ||||
|     [PA_COMMAND_DRAIN_PLAYBACK_STREAM] = "DRAIN_PLAYBACK_STREAM", | ||||
|     [PA_COMMAND_PLAYBACK_STREAM_KILLED] = "PLAYBACK_STREAM_KILLED", | ||||
|     [PA_COMMAND_RECORD_STREAM_KILLED] = "RECORD_STREAM_KILLED", | ||||
|     [PA_COMMAND_STAT] = "STAT", | ||||
|     [PA_COMMAND_GET_PLAYBACK_LATENCY] = "PLAYBACK_LATENCY", | ||||
| }; | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| struct reply_info { | ||||
|     struct pa_pdispatch *pdispatch; | ||||
|     struct reply_info *next, *previous; | ||||
|  | @ -106,7 +114,9 @@ int pa_pdispatch_run(struct pa_pdispatch *pd, struct pa_packet*packet, void *use | |||
|         pa_tagstruct_getu32(ts, &tag) < 0) | ||||
|         goto finish; | ||||
| 
 | ||||
|     /*fprintf(stderr, __FILE__": Recieved opcode <%s>\n", command_names[command]);*/ | ||||
| #ifdef DEBUG_OPCODES | ||||
|     fprintf(stderr, __FILE__": Recieved opcode <%s>\n", command_names[command]); | ||||
| #endif | ||||
| 
 | ||||
|     if (command == PA_COMMAND_ERROR || command == PA_COMMAND_REPLY) { | ||||
|         struct reply_info *r; | ||||
|  |  | |||
							
								
								
									
										51
									
								
								src/polyp.c
									
										
									
									
									
								
							
							
						
						
									
										51
									
								
								src/polyp.c
									
										
									
									
									
								
							|  | @ -89,6 +89,9 @@ struct pa_stream { | |||
|      | ||||
|     void (*die_callback)(struct pa_stream*c, void *userdata); | ||||
|     void *die_userdata; | ||||
| 
 | ||||
|     void (*get_latency_callback)(struct pa_stream*c, uint32_t latency, void *userdata); | ||||
|     void *get_latency_userdata; | ||||
| }; | ||||
| 
 | ||||
| static void command_request(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); | ||||
|  | @ -602,6 +605,8 @@ struct pa_stream* pa_stream_new( | |||
|     s->die_userdata = NULL; | ||||
|     s->create_complete_callback = complete; | ||||
|     s->create_complete_userdata = NULL; | ||||
|     s->get_latency_callback = NULL; | ||||
|     s->get_latency_userdata = NULL; | ||||
| 
 | ||||
|     s->name = strdup(name); | ||||
|     s->state = STREAM_CREATING; | ||||
|  | @ -895,3 +900,49 @@ void pa_context_stat(struct pa_context *c, void (*cb)(struct pa_context *c, uint | |||
|     pa_pstream_send_tagstruct(c->pstream, t); | ||||
|     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_stat_callback, c); | ||||
| } | ||||
| 
 | ||||
| static void stream_get_latency_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { | ||||
|     struct pa_stream *s = userdata; | ||||
|     uint32_t latency; | ||||
|     assert(pd && s); | ||||
| 
 | ||||
|     if (command != PA_COMMAND_REPLY) { | ||||
|         if (handle_error(s->context, command, t) < 0) { | ||||
|             context_dead(s->context); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         if (s->get_latency_callback) | ||||
|             s->get_latency_callback(s, (uint32_t) -1, s->get_latency_userdata); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if (pa_tagstruct_getu32(t, &latency) < 0 || | ||||
|         !pa_tagstruct_eof(t)) { | ||||
|         s->context->error = PA_ERROR_PROTOCOL; | ||||
|         context_dead(s->context); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if (s->get_latency_callback) | ||||
|         s->get_latency_callback(s, latency, s->get_latency_userdata); | ||||
| } | ||||
| 
 | ||||
| void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata) { | ||||
|     uint32_t tag; | ||||
|     struct pa_tagstruct *t; | ||||
| 
 | ||||
|     p->get_latency_callback = cb; | ||||
|     p->get_latency_userdata = userdata; | ||||
| 
 | ||||
|     if (cb == NULL) | ||||
|         return; | ||||
|      | ||||
|     t = pa_tagstruct_new(NULL, 0); | ||||
|     assert(t); | ||||
|     pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY); | ||||
|     pa_tagstruct_putu32(t, tag = p->context->ctag++); | ||||
|     pa_tagstruct_putu32(t, p->channel); | ||||
|     pa_pstream_send_tagstruct(p->context->pstream, t); | ||||
|     pa_pdispatch_register_reply(p->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, p); | ||||
| } | ||||
|  |  | |||
|  | @ -66,6 +66,8 @@ void pa_stream_set_read_callback(struct pa_stream *p, void (*cb)(struct pa_strea | |||
| int pa_stream_is_dead(struct pa_stream *p); | ||||
| int pa_stream_is_ready(struct pa_stream*p); | ||||
| 
 | ||||
| void pa_stream_get_latency(struct pa_stream *p, void (*cb)(struct pa_stream *p, uint32_t latency, void *userdata), void *userdata); | ||||
| 
 | ||||
| struct pa_context* pa_stream_get_context(struct pa_stream *p); | ||||
| 
 | ||||
| #endif | ||||
|  |  | |||
|  | @ -19,6 +19,7 @@ enum { | |||
|     PA_COMMAND_PLAYBACK_STREAM_KILLED, | ||||
|     PA_COMMAND_RECORD_STREAM_KILLED, | ||||
|     PA_COMMAND_STAT, | ||||
|     PA_COMMAND_GET_PLAYBACK_LATENCY, | ||||
|     PA_COMMAND_MAX | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -76,6 +76,7 @@ static void command_auth(struct pa_pdispatch *pd, uint32_t command, uint32_t tag | |||
| static void command_set_name(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); | ||||
| static void command_lookup(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); | ||||
| static void command_stat(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); | ||||
| static void command_get_playback_latency(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata); | ||||
| 
 | ||||
| static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { | ||||
|     [PA_COMMAND_ERROR] = { NULL }, | ||||
|  | @ -93,6 +94,7 @@ static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { | |||
|     [PA_COMMAND_LOOKUP_SINK] = { command_lookup }, | ||||
|     [PA_COMMAND_LOOKUP_SOURCE] = { command_lookup }, | ||||
|     [PA_COMMAND_STAT] = { command_stat }, | ||||
|     [PA_COMMAND_GET_PLAYBACK_LATENCY] = { command_get_playback_latency }, | ||||
| }; | ||||
| 
 | ||||
| /* structure management */ | ||||
|  | @ -664,6 +666,38 @@ static void command_stat(struct pa_pdispatch *pd, uint32_t command, uint32_t tag | |||
|     pa_pstream_send_tagstruct(c->pstream, reply); | ||||
| } | ||||
| 
 | ||||
| static void command_get_playback_latency(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { | ||||
|     struct connection *c = userdata; | ||||
|     assert(c && t); | ||||
|     struct pa_tagstruct *reply; | ||||
|     struct playback_stream *s; | ||||
|     uint32_t index, latency; | ||||
| 
 | ||||
|     if (pa_tagstruct_getu32(t, &index) < 0 || | ||||
|         !pa_tagstruct_eof(t)) { | ||||
|         protocol_error(c); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if (!c->authorized) { | ||||
|         pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if (!(s = pa_idxset_get_by_index(c->playback_streams, index))) { | ||||
|         pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     latency = pa_sink_input_get_latency(s->sink_input); | ||||
|     reply = pa_tagstruct_new(NULL, 0); | ||||
|     assert(reply); | ||||
|     pa_tagstruct_putu32(reply, PA_COMMAND_REPLY); | ||||
|     pa_tagstruct_putu32(reply, tag); | ||||
|     pa_tagstruct_putu32(reply, latency); | ||||
|     pa_pstream_send_tagstruct(c->pstream, reply); | ||||
| } | ||||
| 
 | ||||
| /*** pstream callbacks ***/ | ||||
| 
 | ||||
| static void pstream_packet_callback(struct pa_pstream *p, struct pa_packet *packet, void *userdata) { | ||||
|  |  | |||
							
								
								
									
										12
									
								
								src/todo
									
										
									
									
									
								
							
							
						
						
									
										12
									
								
								src/todo
									
										
									
									
									
								
							|  | @ -1,8 +1,3 @@ | |||
| - pactl | ||||
| 
 | ||||
| - native library/protocol: | ||||
|        more functions (esp. latency) | ||||
| 
 | ||||
| - xmms+esound latency testing | ||||
| 
 | ||||
| - prefix modules/libraries with pa_ | ||||
|  | @ -21,7 +16,12 @@ | |||
| - modinfo | ||||
| - move the global memblock statistics variables to the core | ||||
| - unix socket directories include user name | ||||
| 
 | ||||
| - more complete pactl | ||||
| - native library/protocol: | ||||
|    get server layout  | ||||
|    subscription | ||||
|    module load/unload | ||||
|    kill client/... | ||||
| 
 | ||||
| drivers: | ||||
| - libao | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lennart Poettering
						Lennart Poettering