Notify port available status changes, and update protocol version

The recommended way of setting available status is to call
pa_device_port_set_available, which will send a subscription event
to the relevant card. It will also fire a hook.

Signed-off-by: David Henningsson <david.henningsson@canonical.com>
This commit is contained in:
David Henningsson 2011-11-25 15:17:14 +01:00 committed by Tanu Kaskinen
parent 0dced7f275
commit 47f28a5843
9 changed files with 67 additions and 11 deletions

View file

@ -288,6 +288,11 @@ PA_COMMAND_GET_(SOURCE|SINK)_OUTPUT_INFO_LIST):
The field is added once for every port. The field is added once for every port.
## v25, implemented by >= 2.0
When port availability changes, send a subscription event for the
owning card.
#### If you just changed the protocol, read this #### If you just changed the protocol, read this
## module-tunnel depends on the sink/source/sink-input/source-input protocol ## module-tunnel depends on the sink/source/sink-input/source-input protocol
## internals, so if you changed these, you might have broken module-tunnel. ## internals, so if you changed these, you might have broken module-tunnel.

View file

@ -36,7 +36,7 @@ AC_SUBST(PA_MINOR, pa_minor)
AC_SUBST(PA_MAJORMINOR, pa_major.pa_minor) AC_SUBST(PA_MAJORMINOR, pa_major.pa_minor)
AC_SUBST(PA_API_VERSION, 12) AC_SUBST(PA_API_VERSION, 12)
AC_SUBST(PA_PROTOCOL_VERSION, 24) AC_SUBST(PA_PROTOCOL_VERSION, 25)
# The stable ABI for client applications, for the version info x:y:z # The stable ABI for client applications, for the version info x:y:z
# always will hold y=z # always will hold y=z

View file

@ -4286,9 +4286,10 @@ void pa_alsa_profile_set_dump(pa_alsa_profile_set *ps) {
pa_alsa_decibel_fix_dump(db_fix); pa_alsa_decibel_fix_dump(db_fix);
} }
void pa_alsa_add_ports(pa_hashmap **p, pa_alsa_path_set *ps) { void pa_alsa_add_ports(pa_core *c, pa_hashmap **p, pa_alsa_path_set *ps) {
pa_alsa_path *path; pa_alsa_path *path;
pa_assert(c);
pa_assert(p); pa_assert(p);
pa_assert(!*p); pa_assert(!*p);
pa_assert(ps); pa_assert(ps);
@ -4313,7 +4314,7 @@ void pa_alsa_add_ports(pa_hashmap **p, pa_alsa_path_set *ps) {
pa_device_port *port; pa_device_port *port;
pa_alsa_port_data *data; pa_alsa_port_data *data;
port = pa_device_port_new(s->name, s->description, sizeof(pa_alsa_port_data)); port = pa_device_port_new(c, s->name, s->description, sizeof(pa_alsa_port_data));
port->priority = s->priority; port->priority = s->priority;
data = PA_DEVICE_PORT_DATA(port); data = PA_DEVICE_PORT_DATA(port);
@ -4338,7 +4339,7 @@ void pa_alsa_add_ports(pa_hashmap **p, pa_alsa_path_set *ps) {
/* If there is no or just one setting we only need a /* If there is no or just one setting we only need a
* single entry */ * single entry */
port = pa_device_port_new(path->name, path->description, sizeof(pa_alsa_port_data)); port = pa_device_port_new(c, path->name, path->description, sizeof(pa_alsa_port_data));
port->priority = path->priority * 100; port->priority = path->priority * 100;
@ -4362,7 +4363,7 @@ void pa_alsa_add_ports(pa_hashmap **p, pa_alsa_path_set *ps) {
else else
d = pa_xstrdup(path->description); d = pa_xstrdup(path->description);
port = pa_device_port_new(n, d, sizeof(pa_alsa_port_data)); port = pa_device_port_new(c, n, d, sizeof(pa_alsa_port_data));
port->priority = path->priority * 100 + s->priority; port->priority = path->priority * 100 + s->priority;
pa_xfree(n); pa_xfree(n);

View file

@ -323,6 +323,6 @@ struct pa_alsa_port_data {
pa_alsa_setting *setting; pa_alsa_setting *setting;
}; };
void pa_alsa_add_ports(pa_hashmap **p, pa_alsa_path_set *ps); void pa_alsa_add_ports(pa_core *c, pa_hashmap **p, pa_alsa_path_set *ps);
#endif #endif

View file

@ -2224,7 +2224,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
} }
if (u->mixer_path_set) if (u->mixer_path_set)
pa_alsa_add_ports(&data.ports, u->mixer_path_set); pa_alsa_add_ports(u->core, &data.ports, u->mixer_path_set);
u->sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE | PA_SINK_LATENCY | (u->use_tsched ? PA_SINK_DYNAMIC_LATENCY : 0) | u->sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE | PA_SINK_LATENCY | (u->use_tsched ? PA_SINK_DYNAMIC_LATENCY : 0) |
(set_formats ? PA_SINK_SET_FORMATS : 0)); (set_formats ? PA_SINK_SET_FORMATS : 0));

View file

@ -1950,7 +1950,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
} }
if (u->mixer_path_set) if (u->mixer_path_set)
pa_alsa_add_ports(&data.ports, u->mixer_path_set); pa_alsa_add_ports(u->core, &data.ports, u->mixer_path_set);
u->source = pa_source_new(m->core, &data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY|(u->use_tsched ? PA_SOURCE_DYNAMIC_LATENCY : 0)); u->source = pa_source_new(m->core, &data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY|(u->use_tsched ? PA_SOURCE_DYNAMIC_LATENCY : 0));
pa_source_new_data_done(&data); pa_source_new_data_done(&data);

View file

@ -113,6 +113,7 @@ typedef enum pa_core_hook {
PA_CORE_HOOK_CARD_PUT, PA_CORE_HOOK_CARD_PUT,
PA_CORE_HOOK_CARD_UNLINK, PA_CORE_HOOK_CARD_UNLINK,
PA_CORE_HOOK_CARD_PROFILE_CHANGED, PA_CORE_HOOK_CARD_PROFILE_CHANGED,
PA_CORE_HOOK_PORT_AVAILABLE_CHANGED,
PA_CORE_HOOK_MAX PA_CORE_HOOK_MAX
} pa_core_hook_t; } pa_core_hook_t;

View file

@ -21,11 +21,49 @@
USA. USA.
***/ ***/
#include "device-port.h" #include "device-port.h"
#include <pulsecore/card.h>
PA_DEFINE_PUBLIC_CLASS(pa_device_port, pa_object); PA_DEFINE_PUBLIC_CLASS(pa_device_port, pa_object);
void pa_device_port_set_available(pa_device_port *p, pa_port_available_t status)
{
uint32_t state;
pa_card *card;
/* pa_source *source;
pa_sink *sink; */
pa_core *core;
pa_assert(p);
if (p->available == status)
return;
pa_assert(status != PA_PORT_AVAILABLE_UNKNOWN);
p->available = status;
pa_log_debug("Setting port %s to status %s", p->name, status == PA_PORT_AVAILABLE_YES ? "yes" : "no");
/* Post subscriptions to the card which owns us */
pa_assert_se(core = p->core);
PA_IDXSET_FOREACH(card, core->cards, state)
if (p == pa_hashmap_get(card->ports, p->name))
pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_CHANGE, card->index);
#if 0
/* This stuff is temporarily commented out while figuring out whether to actually do this */
if (p->is_output)
PA_IDXSET_FOREACH(sink, core->sinks, state)
if (p == pa_hashmap_get(sink->ports, p->name))
pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, sink->index);
if (p->is_input)
PA_IDXSET_FOREACH(source, core->sources, state)
if (p == pa_hashmap_get(source->ports, p->name))
pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, source->index);
#endif
pa_hook_fire(&core->hooks[PA_CORE_HOOK_PORT_AVAILABLE_CHANGED], p);
}
static void device_port_free(pa_object *o) { static void device_port_free(pa_object *o) {
pa_device_port *p = PA_DEVICE_PORT(o); pa_device_port *p = PA_DEVICE_PORT(o);
@ -40,7 +78,7 @@ static void device_port_free(pa_object *o) {
} }
pa_device_port *pa_device_port_new(const char *name, const char *description, size_t extra) { pa_device_port *pa_device_port_new(pa_core *c, const char *name, const char *description, size_t extra) {
pa_device_port *p; pa_device_port *p;
pa_assert(name); pa_assert(name);
@ -50,6 +88,7 @@ pa_device_port *pa_device_port_new(const char *name, const char *description, si
p->name = pa_xstrdup(name); p->name = pa_xstrdup(name);
p->description = pa_xstrdup(description); p->description = pa_xstrdup(description);
p->core = c;
p->priority = 0; p->priority = 0;
p->available = PA_PORT_AVAILABLE_UNKNOWN; p->available = PA_PORT_AVAILABLE_UNKNOWN;
p->profiles = NULL; p->profiles = NULL;

View file

@ -35,10 +35,15 @@
#include <pulsecore/object.h> #include <pulsecore/object.h>
#include <pulsecore/hashmap.h> #include <pulsecore/hashmap.h>
/* Note: Including core.h here leads to circular references
(device-port.h -> core.h -> sink.h -> device-port.h), hence the line below instead */
typedef struct pa_core pa_core;
typedef struct pa_device_port pa_device_port; typedef struct pa_device_port pa_device_port;
struct pa_device_port { struct pa_device_port {
pa_object parent; /* Needed for reference counting */ pa_object parent; /* Needed for reference counting */
pa_core *core;
char *name; char *name;
char *description; char *description;
@ -58,8 +63,13 @@ PA_DECLARE_PUBLIC_CLASS(pa_device_port);
#define PA_DEVICE_PORT_DATA(d) ((void*) ((uint8_t*) d + PA_ALIGN(sizeof(pa_device_port)))) #define PA_DEVICE_PORT_DATA(d) ((void*) ((uint8_t*) d + PA_ALIGN(sizeof(pa_device_port))))
pa_device_port *pa_device_port_new(const char *name, const char *description, size_t extra); pa_device_port *pa_device_port_new(pa_core *c, const char *name, const char *description, size_t extra);
void pa_device_port_hashmap_free(pa_hashmap *h); void pa_device_port_hashmap_free(pa_hashmap *h);
#include <pulsecore/core.h>
/* The port's available status has changed */
void pa_device_port_set_available(pa_device_port *p, pa_port_available_t available);
#endif #endif