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
Remove the monitor API, we can use the device API for it. Make sure
we support creating devices (like alsa) from another device (udev).
Use new object.id to store the object id in the object properties. Use
the port.id/node.id etc to make relations to other objects.
Always add work to the work queue, some code relies on the fact that
the state change continuation happens from next iteration of the
mainloop.
Don't warn when destroying the work queue and there are still items in
it, this is ok.
Not closing the fd causes leaks in existing apps. It's probably better
to always close it and let apps deal with that by using dup or similar.
Make gst sink and source dup the fd before connect_fd().
Fixes#181
Use the port as the object/seq identifier of the defered work. This
way we can handle feedback links between the same node and identify
what port completed.
Reorganize some things, let the clients update the segment info
in their own activation, then let the server merge it. This avoids
clients stepping on eachother. When looping through the clients,
copy the segment info when we encounter its owner.
Remove the list of segment owners to the activation. This is better
than in the activation because we can then just keep one list of
owners.
Remove the NONBLOCK flag from the eventfd so that we can do blocking
reads as well.
Just keep a reposition owner in the driver activation. This points
to the node that has the reposition info. This avoid complicated
synchronization to keep multiple nodes from stepping on eachother.
Now they can just prepare the reposition info in their activation and
set themselves as the reposition owner. The last one who succeeds
wins.
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.
When the node latency property is changed, trigger a graph recalc
to set the new quantum if needed.
Also update the driver quantum when unassigned nodes are assigned
to a driver.
This makes it easier to keep track of who is responsible for what.
Also remove the valid fields and move them to flags in the segment
info. That way, the owner can update the flags without having to
worry about concurrency.
Keep separate info for the reposition information. We need to do this
to make it possible to seek in other formats than the frame.
Clear out the owner field when the node is destroyed or removed from
the driver.
Place the requested sync and position update flag in the node
activation. This way we can use our existing loop to update the node
sync states and check if the node is ready.
Implement sync timeout, when the client can't start or seek within the
timeout, we start RUNNING anyway and hope the client catches up.
Sync is enabled when clients need time to move to a new location.
It's a bit like GStreamer preroll after a seek. Clients that need
time, increment the sync_total. Whenever a seek is done, the server
waits in the Starting state until the sync_pending is 0 (or timeout
later).
Improve atomic operations
Add an offset to apply to the clock time before we can compare to the
segment values. This way we can keep the segment start independent of the
clock values and we only need to adjust the offset when paused. It's
like the base_time in GStreamer to calculate the running time.
Move fields from the io_position to io_segment. The segment contains
the mapping between raw clock time and stream time in various
formats. We keep an array of pending segments available in the
io_position field so clients can anticipate changes.
Make looping a flag in the segment instead of a state.
Prepare for segment masters. These will be registered clients that
are responsible for updating parts of the extended segment info.
Add namespace to some defines.
Move some things around. Move the duration of the current cycle
to the clock. Also add the estimated next timeout to the clock.
Add a generic media specific counter to the clock.
Clean up the position_bar info. We can do with only a double beat
value and make the signature in floats.
Flesh out the io_position info. This has now the information needed
to convert a raw clock time into a stream time. It basically has
the same kind of features as GStreamer segments such as looping,
variable rate playback etc.. It also contains the state of the
timeline (paused/playing) and it can be used to update the position
and state from clients.
There is also extended information in the position field that
clients can update when they can.
Plugins basically only update the clock info they get (and use
the position info to check if they are slaved or not).
Before each cycle, check if there is a pending position update and
apply it.
Add flag to always assign a node to a driver. This makes sure that
even when the node is not linked to anything, it will still be
scheduled by an active driver. This is needed for JACK support.