Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions include/libremidi/backends/linux/pipewire/context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,13 @@ class context : public std::enable_shared_from_this<context>
}
return 0;
};
pw_loop_invoke(m_loop, trampoline, 0, nullptr, 0, /*block=*/true, &f);
// A blocking pw_loop_invoke from a foreign thread fires the loop
// control hooks (thread-loop unlock before the wait / lock after),
// which REQUIRE the caller to hold the thread-loop lock. Calling
// without it underflows the recurse counter (refused unlock) and
// then acquires the mutex on the way out, deadlocking the loop.
with_lock(
[&] { pw_loop_invoke(m_loop, trampoline, 0, nullptr, 0, /*block=*/true, &f); });
}
else
{
Expand All @@ -330,7 +336,9 @@ class context : public std::enable_shared_from_this<context>
}
return 0;
};
pw_loop_invoke(m_loop, trampoline, 0, nullptr, 0, /*block=*/true, &p);
// See the void branch: blocking invokes require the thread-loop lock.
with_lock(
[&] { pw_loop_invoke(m_loop, trampoline, 0, nullptr, 0, /*block=*/true, &p); });
return std::move(*p.result);
}
}
Expand Down
7 changes: 6 additions & 1 deletion include/libremidi/backends/linux/pipewire/format.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -320,10 +320,15 @@ inline const spa_pod* format_negotiation::build_buffers_param(
data_type = (1u << SPA_DATA_MemPtr);
break;
}
// size/stride are RANGES with our tight computation as the minimum:
// producers commonly deliver row-padded buffers (GPU-allocated strides),
// and a fixed Int here fails the param intersection against any producer
// whose size differs — killing the link instead of accepting padding.
return reinterpret_cast<const spa_pod*>(spa_pod_builder_add_object(
&builder, SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers, SPA_PARAM_BUFFERS_buffers,
SPA_POD_CHOICE_RANGE_Int(8, 2, 16), SPA_PARAM_BUFFERS_blocks, SPA_POD_Int(blocks),
SPA_PARAM_BUFFERS_size, SPA_POD_Int(size), SPA_PARAM_BUFFERS_stride, SPA_POD_Int(stride),
SPA_PARAM_BUFFERS_size, SPA_POD_CHOICE_RANGE_Int(size, size, INT32_MAX),
SPA_PARAM_BUFFERS_stride, SPA_POD_CHOICE_RANGE_Int(stride, stride, INT32_MAX),
SPA_PARAM_BUFFERS_dataType, SPA_POD_CHOICE_FLAGS_Int(data_type)));
}

Expand Down
Loading