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; return -1;
} }
sink->volume = (uint32_t) volume; pa_sink_set_volume(sink, (uint32_t) volume);
return 0; 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) { void pa_module_set_used(struct pa_module*m, int used) {
assert(m); 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) if (m->n_used != used && used == 0)
time(&m->last_used_time); time(&m->last_used_time);

View file

@ -55,7 +55,9 @@ enum {
PA_COMMAND_GET_SOURCE_INFO, PA_COMMAND_GET_SOURCE_INFO,
PA_COMMAND_GET_SOURCE_INFO_LIST, PA_COMMAND_GET_SOURCE_INFO_LIST,
PA_COMMAND_GET_MODULE_INFO, PA_COMMAND_GET_MODULE_INFO,
PA_COMMAND_GET_MODULE_INFO_LIST,
PA_COMMAND_GET_CLIENT_INFO, PA_COMMAND_GET_CLIENT_INFO,
PA_COMMAND_GET_CLIENT_INFO_LIST,
PA_COMMAND_GET_SINK_INPUT_INFO, PA_COMMAND_GET_SINK_INPUT_INFO,
PA_COMMAND_GET_SOURCE_OUTPUT_INFO, PA_COMMAND_GET_SOURCE_OUTPUT_INFO,
PA_COMMAND_GET_SAMPLE_INFO, PA_COMMAND_GET_SAMPLE_INFO,

View file

@ -24,7 +24,7 @@
#load module-alsa-source device=plughw:1,0 #load module-alsa-source device=plughw:1,0
#load module-oss device="/dev/dsp" sink_name=output source_name=input #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-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 # 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_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_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_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_sink_add output module-alsa-sink sink_name=output
autoload_source_add input module-alsa-source source_name=input #autoload_source_add input module-alsa-source source_name=input
# Load several protocols # Load several protocols
load module-esound-protocol-tcp load module-esound-protocol-tcp

View file

@ -102,6 +102,12 @@ struct pa_context {
void *subscribe_userdata; void *subscribe_userdata;
enum pa_subscription_mask subscribe_mask; 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]; 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_callback = NULL;
c->subscribe_userdata = 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(); pa_check_for_sigpipe();
return c; 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_pstream_send_tagstruct(c->pstream, t);
pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, context_get_source_info_callback, c); 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); 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); 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 #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_REMOVE_SAMPLE] = { command_remove_sample },
[PA_COMMAND_GET_SINK_INFO] = { command_get_info }, [PA_COMMAND_GET_SINK_INFO] = { command_get_info },
[PA_COMMAND_GET_SOURCE_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_SINK_INFO_LIST] = { command_get_info_list },
[PA_COMMAND_GET_SOURCE_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_GET_SERVER_INFO] = { command_get_server_info },
[PA_COMMAND_SUBSCRIBE] = { command_subscribe }, [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 : ""); 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) { 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; struct connection *c = userdata;
uint32_t index; uint32_t index;
struct pa_sink *sink = NULL; struct pa_sink *sink = NULL;
struct pa_source *source = NULL; struct pa_source *source = NULL;
struct pa_client *client = NULL;
struct pa_module *module = NULL;
const char *name; const char *name;
struct pa_tagstruct *reply; struct pa_tagstruct *reply;
assert(c && t); 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); sink = pa_idxset_get_by_index(c->protocol->core->sinks, index);
else else
sink = pa_namereg_get(c->protocol->core, *name ? name : NULL, PA_NAMEREG_SINK, 1); sink = pa_namereg_get(c->protocol->core, *name ? name : NULL, PA_NAMEREG_SINK, 1);
} else { } else if (command == PA_COMMAND_GET_SOURCE_INFO) {
assert(command == PA_COMMAND_GET_SOURCE_INFO);
if (index != (uint32_t) -1) if (index != (uint32_t) -1)
source = pa_idxset_get_by_index(c->protocol->core->sources, index); source = pa_idxset_get_by_index(c->protocol->core->sources, index);
else else
source = pa_namereg_get(c->protocol->core, *name ? name : NULL, PA_NAMEREG_SOURCE, 1); 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); pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
return; return;
} }
@ -1009,8 +1036,12 @@ static void command_get_info(struct pa_pdispatch *pd, uint32_t command, uint32_t
pa_tagstruct_putu32(reply, tag); pa_tagstruct_putu32(reply, tag);
if (sink) if (sink)
sink_fill_tagstruct(reply, sink); sink_fill_tagstruct(reply, sink);
else else if (source)
source_fill_tagstruct(reply, 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); 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) if (command == PA_COMMAND_GET_SINK_INFO_LIST)
i = c->protocol->core->sinks; i = c->protocol->core->sinks;
else { else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST)
assert(command == PA_COMMAND_GET_SOURCE_INFO_LIST);
i = c->protocol->core->sources; 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)) { for (p = pa_idxset_first(i, &index); p; p = pa_idxset_next(i, &index)) {
if (command == PA_COMMAND_GET_SINK_INFO_LIST) if (command == PA_COMMAND_GET_SINK_INFO_LIST)
sink_fill_tagstruct(reply, p); sink_fill_tagstruct(reply, p);
else { else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST)
assert(command == PA_COMMAND_GET_SOURCE_INFO_LIST);
source_fill_tagstruct(reply, p); 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); return s->get_latency(s);
} }
void pa_sink_set_owner(struct pa_sink *sink, struct pa_module *m) { void pa_sink_set_owner(struct pa_sink *sink, struct pa_module *m) {
sink->owner = m; sink->owner = m;
if (sink->monitor_source) if (sink->monitor_source)
pa_source_set_owner(sink->monitor_source, m); 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_owner(struct pa_sink *sink, struct pa_module *m);
void pa_sink_set_volume(struct pa_sink *sink, uint32_t volume);
#endif #endif