diff --git a/changelog/next.md b/changelog/next.md index 19638a1..74554b5 100644 --- a/changelog/next.md +++ b/changelog/next.md @@ -17,3 +17,4 @@ - Fixed intermittent `FileView` crashes when updating watched files. - Fixed `ColorQuantizer` deletion crashing if an operation was live. - Fixed crashes when failing to create a `ScreencopyView`. +- Fixed `PwNodePeakMonitor` crashing when sampling a stream with mismatched channels from the node. diff --git a/src/services/pipewire/peak.cpp b/src/services/pipewire/peak.cpp index 64b5c42..2aec7f5 100644 --- a/src/services/pipewire/peak.cpp +++ b/src/services/pipewire/peak.cpp @@ -245,13 +245,14 @@ void PwPeakStream::handleProcess() { if (!this->formatReady || this->stream == nullptr) return; auto* buffer = pw_stream_dequeue_buffer(this->stream); - auto requeue = qScopeGuard([&, this] { pw_stream_queue_buffer(this->stream, buffer); }); if (buffer == nullptr) { qCWarning(logPeak) << "Peak monitor ran out of buffers."; return; } + auto requeue = qScopeGuard([&, this] { pw_stream_queue_buffer(this->stream, buffer); }); + auto* spaBuffer = buffer->buffer; if (spaBuffer == nullptr || spaBuffer->n_datas < 1) { return; @@ -277,7 +278,27 @@ void PwPeakStream::handleProcess() { QVector volumes; if (auto* audioData = dynamic_cast(this->node->boundData)) { - if (!this->node->shouldUseDevice()) volumes = audioData->volumes(); + // Device volumes don't require inverse scaling + if (!this->node->shouldUseDevice()) { + const auto& nchannels = audioData->channels(); + const auto& nvolumes = audioData->volumes(); + + for (const auto channel: this->monitor->mChannels) { + for (auto i = 0; i != nchannels.length(); i++) { + if (nchannels[i] == channel) { + volumes.push_back(nvolumes[i]); + break; + } + } + } + + if (volumes.length() != channelCount) { + qCCritical(logPeak) << this->node + << "is missing channels present in capture stream. Node channels:" + << nchannels << "Stream channels:" << this->monitor->mChannels; + return; + } + } } this->channelPeaks.fill(0.0f, channelCount);