From 886041aab88930108953af0e9e14b39ec9d03809 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 12 Aug 2004 23:25:28 +0000 Subject: add more subscription events add support for clients/modules in native protocol git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@115 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/cli-command.c | 2 +- polyp/module.c | 3 + polyp/native-common.h | 2 + polyp/polypaudio.pa | 6 +- polyp/polyplib.c | 162 ++++++++++++++++++++++++++++++++++++++++++++++++ polyp/polyplib.h | 19 ++++++ polyp/protocol-native.c | 57 ++++++++++++++--- polyp/sink.c | 9 ++- polyp/sink.h | 2 + 9 files changed, 248 insertions(+), 14 deletions(-) (limited to 'polyp') diff --git a/polyp/cli-command.c b/polyp/cli-command.c index 6386d4e4..1d454f2a 100644 --- a/polyp/cli-command.c +++ b/polyp/cli-command.c @@ -300,7 +300,7 @@ static int pa_cli_command_sink_volume(struct pa_core *c, struct pa_tokenizer *t, return -1; } - sink->volume = (uint32_t) volume; + pa_sink_set_volume(sink, (uint32_t) volume); return 0; } diff --git a/polyp/module.c b/polyp/module.c index 849afca4..1deb7cde 100644 --- a/polyp/module.c +++ b/polyp/module.c @@ -218,6 +218,9 @@ void pa_module_unload_request(struct pa_core *c, struct pa_module *m) { void pa_module_set_used(struct pa_module*m, int used) { assert(m); + if (m->n_used != used) + pa_subscription_post(m->core, PA_SUBSCRIPTION_EVENT_MODULE|PA_SUBSCRIPTION_EVENT_CHANGE, m->index); + if (m->n_used != used && used == 0) time(&m->last_used_time); diff --git a/polyp/native-common.h b/polyp/native-common.h index 5e69c805..4d5ab53d 100644 --- a/polyp/native-common.h +++ b/polyp/native-common.h @@ -55,7 +55,9 @@ enum { PA_COMMAND_GET_SOURCE_INFO, PA_COMMAND_GET_SOURCE_INFO_LIST, PA_COMMAND_GET_MODULE_INFO, + PA_COMMAND_GET_MODULE_INFO_LIST, PA_COMMAND_GET_CLIENT_INFO, + PA_COMMAND_GET_CLIENT_INFO_LIST, PA_COMMAND_GET_SINK_INPUT_INFO, PA_COMMAND_GET_SOURCE_OUTPUT_INFO, PA_COMMAND_GET_SAMPLE_INFO, diff --git a/polyp/polypaudio.pa b/polyp/polypaudio.pa index d57f8127..9f8cf860 100755 --- a/polyp/polypaudio.pa +++ b/polyp/polypaudio.pa @@ -24,7 +24,7 @@ #load module-alsa-source device=plughw:1,0 #load module-oss device="/dev/dsp" sink_name=output source_name=input #load module-oss-mmap device="/dev/dsp" sink_name=output source_name=input -#load module-pipe-sink +load module-pipe-sink # Load audio drivers automatically on access @@ -32,8 +32,8 @@ #autoload_source_add input module-oss device="/dev/dsp" sink_name=output source_name=input #autoload_sink_add output module-oss-mmap device="/dev/dsp" sink_name=output source_name=input #autoload_source_add input module-oss-mmap device="/dev/dsp" sink_name=output source_name=input -autoload_sink_add output module-alsa-sink sink_name=output -autoload_source_add input module-alsa-source source_name=input +#autoload_sink_add output module-alsa-sink sink_name=output +#autoload_source_add input module-alsa-source source_name=input # Load several protocols load module-esound-protocol-tcp diff --git a/polyp/polyplib.c b/polyp/polyplib.c index b77d24ea..35001d3d 100644 --- a/polyp/polyplib.c +++ b/polyp/polyplib.c @@ -102,6 +102,12 @@ struct pa_context { void *subscribe_userdata; enum pa_subscription_mask subscribe_mask; + void (*get_client_info_callback)(struct pa_context*c, const struct pa_client_info* i, int is_last, void *userdata); + void *get_client_info_userdata; + + void (*get_module_info_callback)(struct pa_context*c, const struct pa_module_info* i, int is_last, void *userdata); + void *get_module_info_userdata; + uint8_t auth_cookie[PA_NATIVE_COOKIE_LENGTH]; }; @@ -209,6 +215,12 @@ struct pa_context *pa_context_new(struct pa_mainloop_api *mainloop, const char * c->subscribe_callback = NULL; c->subscribe_userdata = NULL; + c->get_client_info_callback = NULL; + c->get_client_info_userdata = NULL; + + c->get_module_info_callback = NULL; + c->get_module_info_userdata = NULL; + pa_check_for_sigpipe(); return c; } @@ -1386,3 +1398,153 @@ void pa_context_get_source_info_by_index(struct pa_context *c, uint32_t index, v pa_pstream_send_tagstruct(c->pstream, t); pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c); } + +static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_client_info_callback) + c->get_client_info_callback(c, NULL, 0, c->get_client_info_userdata); + return; + } + + while (!pa_tagstruct_eof(t)) { + struct pa_client_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.protocol_name) < 0 || + pa_tagstruct_getu32(t, &i.owner_module) < 0) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_client_info_callback) + c->get_client_info_callback(c, &i, 0, c->get_client_info_userdata); + } + + if (c->get_client_info_callback) + c->get_client_info_callback(c, NULL, 1, c->get_client_info_userdata); +} + + +void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_client_info_callback = cb; + c->get_client_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c); +} + +void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_client_info_callback = cb; + c->get_client_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_CLIENT_INFO_LIST); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_client_info_callback, c); +} + +static void context_get_module_info_callback(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { + struct pa_context *c = userdata; + assert(pd && c); + + if (command != PA_COMMAND_REPLY) { + if (handle_error(c, command, t) < 0) { + context_dead(c); + return; + } + + if (c->get_module_info_callback) + c->get_module_info_callback(c, NULL, 0, c->get_module_info_userdata); + return; + } + + while (!pa_tagstruct_eof(t)) { + struct pa_module_info i; + + if (pa_tagstruct_getu32(t, &i.index) < 0 || + pa_tagstruct_gets(t, &i.name) < 0 || + pa_tagstruct_gets(t, &i.argument) < 0 || + pa_tagstruct_getu32(t, &i.n_used) < 0 || + pa_tagstruct_getu32(t, &i.auto_unload) < 0) { + c->error = PA_ERROR_PROTOCOL; + context_dead(c); + return; + } + + if (c->get_module_info_callback) + c->get_module_info_callback(c, &i, 0, c->get_module_info_userdata); + } + + if (c->get_module_info_callback) + c->get_module_info_callback(c, NULL, 1, c->get_module_info_userdata); +} + +void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_module_info_callback = cb; + c->get_module_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_tagstruct_putu32(t, index); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c); +} + +void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata) { + struct pa_tagstruct *t; + uint32_t tag; + assert(c); + + c->get_module_info_callback = cb; + c->get_module_info_userdata = userdata; + + if (!cb) + return; + + t = pa_tagstruct_new(NULL, 0); + assert(t); + pa_tagstruct_putu32(t, PA_COMMAND_GET_MODULE_INFO_LIST); + pa_tagstruct_putu32(t, tag = c->ctag++); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_module_info_callback, c); +} diff --git a/polyp/polyplib.h b/polyp/polyplib.h index 8708cd72..590b978f 100644 --- a/polyp/polyplib.h +++ b/polyp/polyplib.h @@ -141,6 +141,25 @@ struct pa_server_info { void pa_context_get_server_info(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_server_info*i, void *userdata), void *userdata); +struct pa_module_info { + uint32_t index; + const char*name, *argument; + uint32_t n_used, auto_unload; +}; + +void pa_context_get_module_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata); +void pa_context_get_module_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_module_info*i, int is_last, void *userdata), void *userdata); + +struct pa_client_info { + uint32_t index; + const char *name; + uint32_t owner_module; + const char *protocol_name; +}; + +void pa_context_get_client_info(struct pa_context *c, uint32_t index, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); +void pa_context_get_client_info_list(struct pa_context *c, void (*cb)(struct pa_context *c, const struct pa_client_info*i, int is_last, void *userdata), void *userdata); + void pa_context_subscribe(struct pa_context *c, enum pa_subscription_mask m, void (*cb)(struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata); #ifdef __cplusplus diff --git a/polyp/protocol-native.c b/polyp/protocol-native.c index caaa1396..247851fc 100644 --- a/polyp/protocol-native.c +++ b/polyp/protocol-native.c @@ -159,8 +159,12 @@ static const struct pa_pdispatch_command command_table[PA_COMMAND_MAX] = { [PA_COMMAND_REMOVE_SAMPLE] = { command_remove_sample }, [PA_COMMAND_GET_SINK_INFO] = { command_get_info }, [PA_COMMAND_GET_SOURCE_INFO] = { command_get_info }, + [PA_COMMAND_GET_CLIENT_INFO] = { command_get_info }, + [PA_COMMAND_GET_MODULE_INFO] = { command_get_info }, [PA_COMMAND_GET_SINK_INFO_LIST] = { command_get_info_list }, [PA_COMMAND_GET_SOURCE_INFO_LIST] = { command_get_info_list }, + [PA_COMMAND_GET_MODULE_INFO_LIST] = { command_get_info_list }, + [PA_COMMAND_GET_CLIENT_INFO_LIST] = { command_get_info_list }, [PA_COMMAND_GET_SERVER_INFO] = { command_get_server_info }, [PA_COMMAND_SUBSCRIBE] = { command_subscribe }, }; @@ -964,11 +968,30 @@ static void source_fill_tagstruct(struct pa_tagstruct *t, struct pa_source *sour pa_tagstruct_puts(t, source->monitor_of ? source->monitor_of->name : ""); } +static void client_fill_tagstruct(struct pa_tagstruct *t, struct pa_client *client) { + assert(t && client); + pa_tagstruct_putu32(t, client->index); + pa_tagstruct_puts(t, client->name); + pa_tagstruct_puts(t, client->protocol_name); + pa_tagstruct_putu32(t, client->owner ? client->owner->index : (uint32_t) -1); +} + +static void module_fill_tagstruct(struct pa_tagstruct *t, struct pa_module *module) { + assert(t && module); + pa_tagstruct_putu32(t, module->index); + pa_tagstruct_puts(t, module->name); + pa_tagstruct_puts(t, module->argument ? module->argument : ""); + pa_tagstruct_putu32(t, module->n_used); + pa_tagstruct_putu32(t, module->auto_unload); +} + static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t tag, struct pa_tagstruct *t, void *userdata) { struct connection *c = userdata; uint32_t index; struct pa_sink *sink = NULL; struct pa_source *source = NULL; + struct pa_client *client = NULL; + struct pa_module *module = NULL; const char *name; struct pa_tagstruct *reply; assert(c && t); @@ -990,15 +1013,19 @@ static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t sink = pa_idxset_get_by_index(c->protocol->core->sinks, index); else sink = pa_namereg_get(c->protocol->core, *name ? name : NULL, PA_NAMEREG_SINK, 1); - } else { - assert(command == PA_COMMAND_GET_SOURCE_INFO); + } else if (command == PA_COMMAND_GET_SOURCE_INFO) { if (index != (uint32_t) -1) source = pa_idxset_get_by_index(c->protocol->core->sources, index); else source = pa_namereg_get(c->protocol->core, *name ? name : NULL, PA_NAMEREG_SOURCE, 1); + } else if (command == PA_COMMAND_GET_CLIENT_INFO) + client = pa_idxset_get_by_index(c->protocol->core->clients, index); + else { + assert(command == PA_COMMAND_GET_MODULE_INFO); + module = pa_idxset_get_by_index(c->protocol->core->modules, index); } - - if (!sink && !source) { + + if (!sink && !source && !client && !module) { pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY); return; } @@ -1009,8 +1036,12 @@ static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t pa_tagstruct_putu32(reply, tag); if (sink) sink_fill_tagstruct(reply, sink); - else + else if (source) source_fill_tagstruct(reply, source); + else if (client) + client_fill_tagstruct(reply, client); + else + module_fill_tagstruct(reply, module); pa_pstream_send_tagstruct(c->pstream, reply); } @@ -1039,17 +1070,25 @@ static void command_get_info_list(struct pa_pdispatch *pd, uint32_t command, uin if (command == PA_COMMAND_GET_SINK_INFO_LIST) i = c->protocol->core->sinks; - else { - assert(command == PA_COMMAND_GET_SOURCE_INFO_LIST); + else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST) i = c->protocol->core->sources; + else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST) + i = c->protocol->core->clients; + else { + assert(command == PA_COMMAND_GET_MODULE_INFO_LIST); + i = c->protocol->core->modules; } for (p = pa_idxset_first(i, &index); p; p = pa_idxset_next(i, &index)) { if (command == PA_COMMAND_GET_SINK_INFO_LIST) sink_fill_tagstruct(reply, p); - else { - assert(command == PA_COMMAND_GET_SOURCE_INFO_LIST); + else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST) source_fill_tagstruct(reply, p); + else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST) + client_fill_tagstruct(reply, p); + else { + assert(command == PA_COMMAND_GET_MODULE_INFO_LIST); + module_fill_tagstruct(reply, p); } } diff --git a/polyp/sink.c b/polyp/sink.c index 7e0e15cd..d9a3ae86 100644 --- a/polyp/sink.c +++ b/polyp/sink.c @@ -276,10 +276,17 @@ uint32_t pa_sink_get_latency(struct pa_sink *s) { return s->get_latency(s); } - void pa_sink_set_owner(struct pa_sink *sink, struct pa_module *m) { sink->owner = m; if (sink->monitor_source) pa_source_set_owner(sink->monitor_source, m); } + +void pa_sink_set_volume(struct pa_sink *sink, uint32_t volume) { + assert(sink); + if (sink->volume != volume) { + pa_subscription_post(sink->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, sink->index); + sink->volume = volume; + } +} diff --git a/polyp/sink.h b/polyp/sink.h index 400d5d04..2aa5d611 100644 --- a/polyp/sink.h +++ b/polyp/sink.h @@ -62,4 +62,6 @@ void pa_sink_notify(struct pa_sink*s); void pa_sink_set_owner(struct pa_sink *sink, struct pa_module *m); +void pa_sink_set_volume(struct pa_sink *sink, uint32_t volume); + #endif -- cgit