For flatpaks we need to be able to support older v0 protocol clients.
To handle this we have:
- the connection detects an old client when it receives the first
message. It can do this by checking the sequence number, on old
versions it contains the message size and is never 0, on new
clients the sequence number is 0.
- We add a new signal at the start of the connection with the detected
version number. This installs the right version of the core proxy.
We also move the binding of the client until the hello message is
received. This way we can have a new client connect (portal),
hand over the connection to an old client, which then removes the
client binding again in the hello request with a v0 version.
There are some changes to the passing of fds in v0 vs v3 which need
to investigated some more.
- bump version of our interfaces to 3. This makes it possible to
have v0 and v3 protocol marshal functions.
- Add version number in the proxy. This is mostly automatically done
internally based on the version numbers the library is compiled
with. Where the version number was in the API before, it is now
actually used to look up the right protocol marshal functions. For
Proxies there is usually just 1 version, the current one. It is the
server that will support different versions.
- Add v0 compat marshal functions to convert from and to v0 format.
This has some complications. v0 has a type map it keeps in sync
with the server. For this we have a static type map with mappings
to our own v3 types. Pods are mostly the same except for objects
that used to have arbitrary pods in v0 vs spa_pod_prop in v3. Also
convert between v0 spa_pod_prop and v3 spa_pod_choice.
Formats and commands are also slightly different so handle those
mappings as well.
We only have marshal functions for the server side (resource)
v0 functions.
- Add v0 compatible client-node again. It's a bit tricky to map, v0
client-node basically lets the server to the mixing and teeing
and just does the processing of the internal node.
Move floatmix to the audiomixer plugin and change the name to
AUDIO_MIXER_DSP.
Add runtime selectable sse and sse2 optimizations.
Load the port mixer plugin dynamically based on the factory_name.
Add some more debug
When the port receives a format, look if we can find a mixer for it
and configure it.
Use the float32 mono mixer when possible.
Use the new pw_buffers in the link.
Let the port allocate buffers between the mixer and node when
requested.
The client-node doesn't need a mixer because mixing is done on the
client.
Remove all mixer and buffer negotiation code from adapter because
it is now done at the port level.
Implement the device reservation DBus API.
When we acquire the device name, set our device profile to 'On'. This
adds our sources and sinks to the graph.
When we lose the name, switch back to 'Off' and remove our nodes
again.
Move the session mamager stuff in a directory.
Fixes#191
This patch is fixing random crashes when vlc player connects rtsp.
we have two places to do link_activate, one is in node_activate(1),
the other one happens on link_paused(2).
The order of (1) and (2) can vary for each different connection.
Sometimes, (1) comes before (2); Sometimes, (1) comes after (2).
This will cause one crash in about five connections from vlc to
rtsp.
If link_paused(2) is earlier than node_activate, it will do set_io
and make activated=true, then when node_activate(1) comes, nothing
will happen:
int pw_link_activate(struct pw_link *this)
{
struct impl *impl = SPA_CONTAINER_OF(this, struct impl, this);
int res;
pw_log_debug(NAME" %p: activate %d %d", this, impl->activated, this->info.state);
if (impl->activated)
return 0;
...
}
In this case, everything works well.
If node_activate(1) is earlier than (2), it will do port_set_io, but
"activated" will still be false after port_set_io since the link state
can be not PW_LINK_STATE_PAUSED:
int pw_link_activate(struct pw_link *this)
{
struct impl *impl = SPA_CONTAINER_OF(this, struct impl, this);
int res;
pw_log_debug(NAME" %p: activate %d %d", this, impl->activated, this->info.state);
if (impl->activated)
return 0;
pw_link_prepare(this);
... // port_set_io
if (this->info.state == PW_LINK_STATE_PAUSED) {
pw_loop_invoke(this->output->node->data_loop,
do_activate_link, SPA_ID_INVALID, NULL, 0, false, this);
impl->activated = true;
}
return 0;
}
Then when link_paused(2) happens after (1), port_set_io will be done
again.
This will lead to random crash of pipewire.
Signed-off-by: Barry Song
Fixes#186
After we grab the lockfile we should remove the socket when it
exists so that we can bind again. This should solve startup
problems after a crash, which left the socket around and caused
bind failures.