1 --- a/src/pulsecore/core.h 2016-04-13 16:38:56.392014788 +0200
2 +++ b/src/pulsecore/core.h 2016-04-13 16:41:50.331014498 +0200
4 PA_CORE_HOOK_CARD_PROFILE_ADDED,
5 PA_CORE_HOOK_CARD_PROFILE_AVAILABLE_CHANGED,
6 PA_CORE_HOOK_PORT_AVAILABLE_CHANGED,
7 + PA_CORE_HOOK_PORT_ACTIVE_CHANGED,
8 PA_CORE_HOOK_PORT_LATENCY_OFFSET_CHANGED,
11 --- a/src/pulsecore/device-port.c 2016-04-13 16:39:37.411014719 +0200
12 +++ b/src/pulsecore/device-port.c 2016-04-13 17:06:47.393011999 +0200
14 pa_hook_fire(&core->hooks[PA_CORE_HOOK_PORT_LATENCY_OFFSET_CHANGED], p);
17 +void pa_device_port_active_changed(pa_device_port *port, bool new_active) {
22 + old_active = port->active;
24 + if (new_active == old_active)
27 + port->active = new_active;
28 + pa_log_debug("Port %s %s.", port->name, new_active ? "activated" : "deactivated");
29 + pa_hook_fire(&port->core->hooks[PA_CORE_HOOK_PORT_ACTIVE_CHANGED], port);
32 pa_device_port *pa_device_port_find_best(pa_hashmap *ports)
35 --- a/src/pulsecore/device-port.h 2016-04-13 16:39:51.603014696 +0200
36 +++ b/src/pulsecore/device-port.h 2016-04-13 17:07:12.649011957 +0200
40 pa_available_t available; /* PA_AVAILABLE_UNKNOWN, PA_AVAILABLE_NO or PA_AVAILABLE_YES */
43 pa_proplist *proplist;
44 pa_hashmap *profiles; /* Does not own the profiles */
45 --- a/src/pulsecore/sink.c 2016-04-13 16:40:11.131014663 +0200
46 +++ b/src/pulsecore/sink.c 2016-04-13 17:14:30.963011225 +0200
49 pa_assert_se(sink_set_state(s, PA_SINK_IDLE) == 0);
52 + pa_device_port_active_changed(s->active_port, true);
54 pa_source_put(s->monitor_source);
56 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_NEW, s->index);
59 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_UNLINK], s);
62 + pa_device_port_active_changed(s->active_port, false);
64 if (s->state != PA_SINK_UNLINKED)
65 pa_namereg_unregister(s->core, s->name);
66 pa_idxset_remove_by_data(s->core->sinks, s, NULL);
68 /* Called from main context */
69 int pa_sink_set_port(pa_sink *s, const char *name, bool save) {
71 + pa_device_port *old_port;
74 pa_sink_assert_ref(s);
75 @@ -3313,11 +3320,15 @@
76 if (!(port = pa_hashmap_get(s->ports, name)))
77 return -PA_ERR_NOENTITY;
79 - if (s->active_port == port) {
80 + old_port = s->active_port;
82 + if (port == old_port) {
83 s->save_port = s->save_port || save;
87 + pa_device_port_active_changed(old_port, false);
89 if (s->flags & PA_SINK_DEFERRED_VOLUME) {
90 struct sink_message_set_port msg = { .port = port, .ret = 0 };
91 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_PORT, &msg, 0, NULL) == 0);
92 @@ -3326,17 +3337,26 @@
94 ret = s->set_port(s, port);
97 - return -PA_ERR_NOENTITY;
99 + pa_log("Failed to set the port of sink %s from %s to %s.", s->name, old_port->name, port->name);
101 + /* We don't know the real state of the device, but let's assume that
102 + * the old port is still active, because s->active_port is left to
103 + * point to the old port anyway. */
104 + pa_device_port_active_changed(old_port, true);
109 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
111 - pa_log_info("Changed port of sink %u \"%s\" to %s", s->index, s->name, port->name);
112 + pa_log_info("Changed port of sink %u \"%s\" from %s to %s", s->index, s->name, old_port->name, port->name);
114 s->active_port = port;
117 pa_sink_set_latency_offset(s, s->active_port->latency_offset);
118 + pa_device_port_active_changed(port, true);
120 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PORT_CHANGED], s);
122 --- a/src/pulsecore/source.c 2016-04-13 16:40:25.290014640 +0200
123 +++ b/src/pulsecore/source.c 2016-04-13 17:21:26.051010533 +0200
126 pa_assert_se(source_set_state(s, PA_SOURCE_IDLE) == 0);
128 + if (s->active_port)
129 + pa_device_port_active_changed(s->active_port, true);
131 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_NEW, s->index);
132 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_PUT], s);
136 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], s);
138 + if (s->active_port)
139 + pa_device_port_active_changed(s->active_port, false);
141 if (s->state != PA_SOURCE_UNLINKED)
142 pa_namereg_unregister(s->core, s->name);
143 pa_idxset_remove_by_data(s->core->sources, s, NULL);
144 @@ -2576,6 +2582,7 @@
145 /* Called from main context */
146 int pa_source_set_port(pa_source *s, const char *name, bool save) {
147 pa_device_port *port;
148 + pa_device_port *old_port;
151 pa_source_assert_ref(s);
152 @@ -2592,11 +2599,15 @@
153 if (!(port = pa_hashmap_get(s->ports, name)))
154 return -PA_ERR_NOENTITY;
156 - if (s->active_port == port) {
157 + old_port = s->active_port;
159 + if (port == old_port) {
160 s->save_port = s->save_port || save;
164 + pa_device_port_active_changed(old_port, false);
166 if (s->flags & PA_SOURCE_DEFERRED_VOLUME) {
167 struct source_message_set_port msg = { .port = port, .ret = 0 };
168 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_PORT, &msg, 0, NULL) == 0);
169 @@ -2605,16 +2616,26 @@
171 ret = s->set_port(s, port);
174 - return -PA_ERR_NOENTITY;
176 + pa_log("Failed to set the port of sink %s from %s to %s.", s->name, old_port->name, port->name);
178 + /* We don't know the real state of the device, but let's assume that
179 + * the old port is still active, because s->active_port is left to
180 + * point to the old port anyway. */
181 + pa_device_port_active_changed(old_port, true);
186 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
188 - pa_log_info("Changed port of source %u \"%s\" to %s", s->index, s->name, port->name);
189 + pa_log_info("Changed port of source %u \"%s\" from %s to %s", s->index, s->name, old_port->name, port->name);
191 s->active_port = port;
194 + pa_device_port_active_changed(port, true);
196 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_PORT_CHANGED], s);