Skip to content

Conversation

@OpatrilPeter
Copy link

Hello,
I've encountered a problem with the current code that caused PulseAudio server 16.1-8-g6f04 (on WSLG) to reject CreatePlaybackStream message with Invalid argument error code.

Examination shown the reason is following code:

CHECK_VALIDITY_GOTO(c->pstream, map.channels == ss.channels && volume.channels == ss.channels, tag, PA_ERR_INVALID, finish);

@ https://github.com/pulseaudio/pulseaudio/blob/86e9c90/src/pulsecore/protocol-native.c#L2026

In short, the server assumes the channel volume has the same amount of channels as the sample spec, but default used when cvolume argument is None always initializes with single channel.

I verified that the fix helped making the audio playback work in Cave Story source port using cpal with your CA support branch with WSL2.

I'd recommend removing the Default implmentation of ChannelVolume altogether as it's error prone due to issue above, but that's out of scope here and would require to rethink defaults for other types too.

@colinmarc
Copy link
Owner

Thanks for the fix, this looks good to me! How hard would it be to add a test that fails before the fix?

@OpatrilPeter
Copy link
Author

OpatrilPeter commented Nov 14, 2025

Good point. I've added some tests and documentation, let me know if this is what you had in mind or would like to trim it down, for example.
I haven't studied the protocol and so I didn't want to actvely test cases where the server fails, as it may not to.

Also, it seems a bit of a shame that SampleFormat::default() is invalid (rejected by my server, at least). Would love to not have to pick arbitrary value in tests unrelated to it.

@colinmarc
Copy link
Owner

This looks great :) fwiw I was actually asking, not making a point - I wasn't sure how hard the behavior is to reproduce in a clean environment.

I just triggered CI, I'll be back at my linux workstation in a few days and can do another test then.

/// Creates a channel map with N (arbitrarily chosen) channels.
///
/// Intended for testing cases where only the number of channels matters.
pub(crate) fn with_n_channels(channels: u8) -> Self {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's just inline this in the tests (or add a function inside the #[cfg(test)] block)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since it's already used in two modules and is in theory useful in any kind of test where you'd want arbitrary ChannelMap in a command (as the channel count must presumably align in any usecase), I think it's better left with the class for now. I added the conditionality, there should be no unused warnings now.

@OpatrilPeter
Copy link
Author

@colinmarc Let me know if you need any further tweaks, I'd love to help wrapping this up.

@colinmarc
Copy link
Owner

colinmarc commented Nov 30, 2025

Merged in 8b8db27. Thanks!!

@colinmarc colinmarc closed this Nov 30, 2025
@colinmarc
Copy link
Owner

@OpatrilPeter would you mind deleting your fork? I'd like to disassociate this with pulsar-rs (since there is basically zero shared code and the upstream repo is gone anyway) but I can't do that if there are "child forks" apparently.

@OpatrilPeter OpatrilPeter deleted the fix_cvolume_default branch December 1, 2025 10:32
@OpatrilPeter
Copy link
Author

@colinmarc Fork deleted, although it seems there are others out there. For the record, there's the option to 'unlink it from the fork network' that would probably also do the trick, so you may suggest this to people as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants