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
This commit is contained in:
Lennart Poettering 2004-08-12 23:25:28 +00:00
parent cbfaf40b45
commit 886041aab8
9 changed files with 248 additions and 14 deletions

View file

@ -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;
}

View file

@ -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);

View file

@ -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,

View file

@ -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

View file

@ -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);
}

View file

@ -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

View file

@ -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);
}
}

View file

@ -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;
}
}

View file

@ -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