Hydrogenaudio Forums

Hosted Forums => foobar2000 => 3rd Party Plugins - (fb2k) => Topic started by: sammoth on 2020-08-23 16:17:06

Title: foo_out_pulse - pulseaudio output
Post by: sammoth on 2020-08-23 16:17:06
Hello, I have made a component for Wine users, to interface directly with Pulseaudio. It's definitely 'beta', hopefully someone finds it useful. In the future I will try to enable streaming to other IPs, for example to allow streaming to a Raspberry Pi or similar. Please see the setup notes.

Home (https://github.com/sammoth/foo_out_pulse)
Download (https://github.com/sammoth/foo_out_pulse/releases)
Title: Re: foo_out_pulse - pulseaudio output
Post by: paregistrase on 2020-08-24 21:06:17
Works great.

Completely remove the pauses when wrting a lot of tags.

Thanks.
Title: Re: foo_out_pulse - pulseaudio output
Post by: kode54 on 2020-08-25 07:48:16
Works great here too. Wondering what's up with the winelib detection mode I saw in the source code. Also awaiting support for linking the foobar2000 volume control with the PulseAudio volume control, as currently, the player's own volume control is non-functional.
Title: Re: foo_out_pulse - pulseaudio output
Post by: sammoth on 2020-08-25 12:12:48
For the client library I'm using the only build of Pulseaudio available for Windows, which is pretty old (v1.1, current version is 13). I had a go at getting the latest version to build but haven't been able to yet.

I was considering ways to allow better intergration by avoiding the need to set up and use the TCP protocol - ie. communicate directly with Pulse's Unix socket like native applications do. There are two ways I can think of to do it. One is by modifying the Pulse library to directly make the syscalls for accessing the socket. The library is pretty complex so that's probably too difficult, especially as I can't even build Pulse yet.

The other is you can build a DLL using wine tooling that exports certain functions as a DLL and implements them using code compiled for Linux. You can therefore build a DLL that exports the same interface as the libpulse, and passes through every function call to the system's native libpulse.so, which then handles the socket connection etc. as usual. This is basically how Wine's own audio implementation works, except that it is more complex as is translates the Windows API to Pulse's. By passing through the libpulse API everything is much simpler, and there is basically no impedance mismatch between foobar's API and pulse's. The advantage of this is that it uses the most up to date client library on your system, which might have improvements at this point such as power use, and it avoids the need for the TCP protocol. The downside is that you're building a wine DLL that links against Wine and Pulse on your system, so I believe you will have to rebuild it for every update of those packages. Also, while it worked well for a while when I was testing it, at one point it started crashing and as you can imagine it's significantly harder to debug.

So overall I think it's not worth pursuing, the possible advantages are quite small anyway. If you are interested you can look at my libpulse-wine repo which builds the DLL, that you can drop in as a replacement to the bundled one.
Title: Re: foo_out_pulse - pulseaudio output
Post by: sammoth on 2020-08-29 16:59:03
I have made a new release, with the following changes

- Custom anti-popping seek/track change fading implementation that keeps PA fully buffered while allowing instant seeking etc. The fading is configurable in Advanced Preferences -> Playback -> Pulseaudio output
- Uses a new Pulseaudio v13 build, should fix sometimes high CPU use after seek or manual track change
- Two way PA volume control integration
- More responsive playback start/track change
- Fix bug playing very short files where playback would be delayed
- Fix hang on last item in playlist

I would be interested to see if anyone has problems with this release seeing as it has a Pulseaudio client library that I compiled myself. It seems OK for me so far. Also any problems with the fading implementation, as it assumes that the fading can be calculated at a certain speed. Maybe on certain setups the assumption will be incorrect.

If it crashes horribly, you can copy the 'pulse' folder from the previous release. The only issue with it is that after seek/track change, sometimes its CPU use will jump up until playback is stopped.

Download (https://github.com/sammoth/foo_out_pulse/releases/tag/v0.2-beta)
Title: Re: foo_out_pulse - pulseaudio output
Post by: michtar on 2020-08-31 00:22:43
v0.1-beta - works
v0.2-beta - playback is sped up, ~25x
Title: Re: foo_out_pulse - pulseaudio output
Post by: sammoth on 2020-08-31 00:30:30
v0.1-beta - works
v0.2-beta - playback is sped up, ~25x

Thank you for testing. Could you try the attached version please?

Could you also send me the output of the command pactl list?
Title: Re: foo_out_pulse - pulseaudio output
Post by: sammoth on 2020-08-31 00:39:00
Sorry, this version
Title: Re: foo_out_pulse - pulseaudio output
Post by: kode54 on 2020-08-31 04:02:43
I tested the 0.2 release on Github already, it works fine. No "speed up" issues.
Title: Re: foo_out_pulse - pulseaudio output
Post by: michtar on 2020-08-31 11:15:07
Tested on fresh, clean, portable install, it worked then the problem returned. It scrolls through a two minute track in five seconds  :o . Must be some obscure hardware/software config issue on my side.

Apologies for wasting time.
Title: Re: foo_out_pulse - pulseaudio output
Post by: sammoth on 2020-08-31 11:21:36
Tested on fresh, clean, portable install, it worked then the problem returned. It scrolls through a two minute track in five seconds  :o . Must be some obscure hardware/software config issue on my side.

Apologies for wasting time.

I think I can see the problem causing the fast playback - I am not handling an error condition properly, instead of failing on error the playback will speed up. I'll add some better error reporting, maybe we can work out what's wrong. I would be interested in knowing your distribution/wine version/output of pactl list still if you have time. Maybe I can set up a similar test envronment.
Title: Re: foo_out_pulse - pulseaudio output
Post by: paregistrase on 2020-08-31 12:14:33
Version 0.2 installed.

I test going back and forward in the songs a lot and not problem at all.

Also now the playback stops correctly at the end of playlist, stop after current and stop after queue.

And the most cool of all; the volume of foobar finally changes the pulseaudio volume.

Title: Re: foo_out_pulse - pulseaudio output
Post by: tawnypigeon on 2020-08-31 12:22:52
Love that you're working on this. I'm having the same superfast playback issue, running Voidlinux, Wine 5.16, and pulseaudio 13.
Do you need the whole pactl list or just the running sink?

Code: [Select]
Sink #0
State: RUNNING
Name: alsa_output.pci-0000_00_1b.0.analog-stereo
Description: Built-in Audio Analog Stereo
Driver: module-alsa-card.c
Sample Specification: s32le 2ch 48000Hz
Channel Map: front-left,front-right
Owner Module: 7
Mute: no
Volume: front-left: 20316 /  31% / -30.52 dB,   front-right: 20316 /  31% / -30.52 dB
        balance 0.00
Base Volume: 65536 / 100% / 0.00 dB
Monitor Source: alsa_output.pci-0000_00_1b.0.analog-stereo.monitor
Latency: 1999385 usec, configured 2000000 usec
Flags: HARDWARE HW_MUTE_CTRL HW_VOLUME_CTRL DECIBEL_VOLUME LATENCY
Properties:
alsa.resolution_bits = "32"
device.api = "alsa"
device.class = "sound"
alsa.class = "generic"
alsa.subclass = "generic-mix"
alsa.name = "CX20756 Analog"
alsa.id = "CX20756 Analog"
alsa.subdevice = "0"
alsa.subdevice_name = "subdevice #0"
alsa.device = "0"
alsa.card = "1"
alsa.card_name = "HDA Intel PCH"
alsa.long_card_name = "HDA Intel PCH at 0xb3614000 irq 51"
alsa.driver_name = "snd_hda_intel"
device.bus_path = "pci-0000:00:1b.0"
sysfs.path = "/devices/pci0000:00/0000:00:1b.0/sound/card1"
device.bus = "pci"
device.vendor.id = "8086"
device.vendor.name = "Intel Corporation"
device.product.id = "9c20"
device.product.name = "8 Series HD Audio Controller"
device.form_factor = "internal"
device.string = "front:1"
device.buffering.buffer_size = "768000"
device.buffering.fragment_size = "384000"
device.access_mode = "mmap+timer"
device.profile.name = "analog-stereo"
device.profile.description = "Analog Stereo"
device.description = "Built-in Audio Analog Stereo"
alsa.mixer_name = "Conexant CX20756"
alsa.components = "HDA:14f15114,1179f922,00100100"
module-udev-detect.discovered = "1"
device.icon_name = "audio-card-pci"
Ports:
analog-output-speaker: Speakers (priority: 10000, not available)
analog-output-headphones: Headphones (priority: 9900, available)
Active Port: analog-output-headphones
Formats:
pcm



Sink Input with your plugin playing at 25x speed:
Code: [Select]
Sink Input #0
Driver: protocol-native.c
Owner Module: 24
Client: 1
Sink: 0
Sample Specification: float32le 2ch 48000Hz
Channel Map: front-left,front-right
Format: pcm, format.sample_format = "\"float32le\""  format.rate = "48000"  format.channels = "2"  format.channel_map = "\"front-left,front-right\""
Corked: no
Mute: no
Volume: front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB
        balance 0.00
Buffer Latency: 0 usec
Sink Latency: 1999162 usec
Resample method: copy
Properties:
media.name = "Audio"
application.name = "foobar2000"
native-protocol.peer = "TCP/IP client from 127.0.0.1:47746"
native-protocol.version = "33"
application.id = "foobar2000"
application.icon_name = "foobar2000"
application.process.id = "32"
application.process.binary = "foobar2000.exe"
application.language = "C"
window.x11.display = ":0"
application.process.machine_id = "pij"
application.process.session_id = "1"
module-stream-restore.id = "sink-input-by-application-id:foobar2000"


Sink Input with the default output playing normally:
Code: [Select]
Sink Input #1
Driver: protocol-native.c
Owner Module: 12
Client: 3
Sink: 0
Sample Specification: float32le 2ch 48000Hz
Channel Map: front-left,front-right
Format: pcm, format.sample_format = "\"float32le\""  format.rate = "48000"  format.channels = "2"  format.channel_map = "\"front-left,front-right\""
Corked: no
Mute: no
Volume: front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB
        balance 0.00
Buffer Latency: 15000 usec
Sink Latency: 5053 usec
Resample method: copy
Properties:
media.name = "audio stream #3"
application.name = "foobar2000.exe"
native-protocol.peer = "UNIX socket client"
native-protocol.version = "33"
application.process.id = "7818"
application.process.binary = "wine-preloader"
application.language = "en_GB.UTF-8"
window.x11.display = ":0"
application.process.machine_id = "beee4f833bf4e74cd586ac5e5da826d4"
application.process.session_id = "1"
module-stream-restore.id = "sink-input-by-application-name:foobar2000.exe"

Obvious difference is
   Buffer Latency: 0 usec
   Sink Latency: 1999162 usec
vs
   Buffer Latency: 15000 usec
   Sink Latency: 5053 usec

Hope that's a help. Let me know if you need the full print.
Title: Re: foo_out_pulse - pulseaudio output
Post by: sammoth on 2020-08-31 12:36:31
Thank you that's actually very useful.
Title: Re: foo_out_pulse - pulseaudio output
Post by: sammoth on 2020-08-31 12:42:14
For your sink,

Code: [Select]
Latency: 1999385 usec, configured 2000000 usec

If you restart Pulseaudio (pulseaudio -k) and don't use my plugin, is the sink latency still set that high initially or is it lower at first?
Title: Re: foo_out_pulse - pulseaudio output
Post by: tawnypigeon on 2020-08-31 13:45:54
Ah, that's just because I set "default-fragments = 2; default-fragment-size-msec = 1000" a while back to try and mitigate some stutter issues I was having. Changed it to default-fragment-size-msec = 300 and your plugin's still playing skippedyquick so I don't think that's related.
Title: Re: foo_out_pulse - pulseaudio output
Post by: sammoth on 2020-08-31 14:19:02
Makes sense, I think the zero buffer is just because of a failure to set up the stream correctly. Would you be able to try changing to interrupt scheduling in PA? You can change it in default.pa, change the line
Code: [Select]
load-module module-udev-detect
to be
Code: [Select]
load-module module-udev-detect tsched=0

You can check it's enabled with
Code: [Select]
pactl list | grep tsched
Title: Re: foo_out_pulse - pulseaudio output
Post by: tawnypigeon on 2020-08-31 15:00:45
That works!

New Sink Input with your plugin playing at normal speed.
Code: [Select]
Sink Input #1
        Driver: protocol-native.c
        Owner Module: 24
        Client: 4
        Sink: 0
        Sample Specification: float32le 2ch 48000Hz
        Channel Map: front-left,front-right
        Format: pcm, format.sample_format = "\"float32le\""  format.rate = "48000"  format.channels = "2"  format.channel_map = "\"front-left,front-right\""
        Corked: no
        Mute: no
        Volume: front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB
                balance 0.00
        Buffer Latency: 1974187 usec
        Sink Latency: 600895 usec
        Resample method: copy
        Properties:
                media.name = "Audio"
                application.name = "foobar2000"
                native-protocol.peer = "TCP/IP client from 127.0.0.1:49614"
                native-protocol.version = "33"
                application.id = "foobar2000"
                application.icon_name = "foobar2000"
                application.process.id = "32"
                application.process.binary = "foobar2000.exe"
                application.language = "C"
                window.x11.display = ":0"
                application.process.machine_id = "pij"
                application.process.session_id = "1"
                module-stream-restore.id = "sink-input-by-application-id:foobar2000"
Title: Re: foo_out_pulse - pulseaudio output
Post by: sammoth on 2020-08-31 15:16:02
OK thanks, I think I have worked out the problem. You can change that option back if you prefer - it's supposed to be better but is problematic on some hardware.
Title: Re: foo_out_pulse - pulseaudio output
Post by: sammoth on 2020-08-31 17:36:34
New version v0.3, hopefully fixes the speed issue. I could reproduce it once but not again - it seems kind of random, so I'd appreciate feedback

Download (https://github.com/sammoth/foo_out_pulse/releases/tag/v0.3-beta)

edit: oh no it looks like it didn't fix it >,<

Title: Re: foo_out_pulse - pulseaudio output
Post by: sammoth on 2020-08-31 18:52:34
Last try:

Download v0.4 (https://github.com/sammoth/foo_out_pulse/releases/tag/v0.4-beta)
Title: Re: foo_out_pulse - pulseaudio output
Post by: marspeople on 2020-09-03 15:01:47
I tried to test this but for some reason I keep getting "connection refused" in the log when trying to play in foobar2000.

I have followed the instructions to add the line to /etc/pulse/default.pa and rebooted but still the same. I'm on Ubuntu 20.04, any ideas?
Title: Re: foo_out_pulse - pulseaudio output
Post by: sammoth on 2020-09-03 16:22:35
After investigating the sped-up playback bug and looking at some similar issues from other projects, I am somewhat convinced it's a bug in Pulseaudio or certain ALSA drivers. I'd suggest using tsched=0 if you have that issue. I have left the workaround in in case it's useful, however it's behind a preference in the advanced preferences page.

This version also has some fixes to smooth out visualisations.

Download 0.5 (https://github.com/sammoth/foo_out_pulse/releases/tag/v0.5-beta)

I tried to test this but for some reason I keep getting "connection refused" in the log when trying to play in foobar2000.

I have followed the instructions to add the line to /etc/pulse/default.pa and rebooted but still the same. I'm on Ubuntu 20.04, any ideas?

Is pulseaudio running? Normally when an application tries to output audio, Pulseaudio is started automatically, however that won't work when using it over the network, so you have to start it yourself. You can start it by running 'pulseaudio -D' or opening pavucontrol and waiting for it to connect.
Title: Re: foo_out_pulse - pulseaudio output
Post by: marspeople on 2020-09-03 17:08:42
Is pulseaudio running? Normally when an application tries to output audio, Pulseaudio is started automatically, however that won't work when using it over the network, so you have to start it yourself. You can start it by running 'pulseaudio -D' or opening pavucontrol and waiting for it to connect.

Yes, it's up and running. I can verify with pavucontrol and foobar2000 recognizes it with the default output component. It's just that when I switch the output to foo_out_pulse I get nothing.

Is there any other way I can test playing something via the native-protocol-tcp module?
Title: Re: foo_out_pulse - pulseaudio output
Post by: sammoth on 2020-09-03 17:16:33
Yes you can try running any other application with the environment variable PULSE_SERVER set to 127.0.0.1, eg

Code: [Select]
PULSE_SERVER=127.0.0.1 mpv test.mp3

If that works, is there any other output in the foobar console when it fails? Could you try with release 0.1 from github?
Title: Re: foo_out_pulse - pulseaudio output
Post by: marspeople on 2020-09-03 18:28:42
If that works, is there any other output in the foobar console when it fails? Could you try with release 0.1 from github?

Thanks for the suggestion, but mpv also didn't work. I got this message: "[ao/pulse] The stream is suspended. Bailing out."

There probably is something wrong with my pulseaudio config, even though I didn't touch it before.
Title: Re: foo_out_pulse - pulseaudio output
Post by: sammoth on 2020-09-03 19:01:55
I just realised that you can use the pulse cookie to authenticate, you just need to copy or link it into your wine prefix. So you don't need to use the 'auth-ip-acl=' option in Pulseaudio's configuration, which is a bit much better from a security perspective. See the updated setup instructions in the readme (https://github.com/sammoth/foo_out_pulse/blob/master/README.md)
Title: Re: foo_out_pulse - pulseaudio output
Post by: kode54 on 2020-09-04 02:08:30
Try killing two modules in your system default.pa configuration, module-role-cork and module-suspend-on-idle, by commenting out the two modules. Then you can use "pacmd unload-module <module-name>" to unload those two modules from the current instance.
Title: Re: foo_out_pulse - pulseaudio output
Post by: marspeople on 2020-09-08 18:01:03
After some digging I was able to fix the issue. On my system there are two pulseaudio instances: one launched under my user and another for gdm. I had to disable the gdm instance and then I could connect via foobar2000.

The component works but unfortunately I still get some occasional audio pops when switching windows or desktops.
Title: Re: foo_out_pulse - pulseaudio output
Post by: sammoth on 2020-09-10 15:53:15
I still get some occasional audio pops when switching windows or desktops.

That's a very extreme version of that problem, does that happen with other apps or just foobar? Switching windows is a pretty lightweight activity
Title: Re: foo_out_pulse - pulseaudio output
Post by: marspeople on 2020-09-10 20:01:12
That's a very extreme version of that problem, does that happen with other apps or just foobar? Switching windows is a pretty lightweight activity

I happens only with foobar, but I guess it may be related to Wine. However, it's not constant. Sometimes the playback is flawless no matter what but other times it gets sensitive on CPU spikes it seems.

I saw similar reports of foobar audio issues under Wine and I was trying to find a way to bypass wineaudio or something. It's not so bad so I guess I can live with it.
Title: Re: foo_out_pulse - pulseaudio output
Post by: sammoth on 2020-09-10 20:08:26
The intention of this component was definitely to try and fix that. Wine does seem to have some problems with audio but this bypasses the normal wine audio stack completely. Of course there still could be problems but as long as foobar doesn't get hung up by Wine for longer than the buffer length, in theory there shouldn't be any dropouts, but clearly it's not helping as much as I hoped. You could try increasing the buffer in foobar's Output settings (as this directly controls the Pulseaudio buffer) and check how long the buffer is when it's playing something, running pactl list sink-inputs and looking for "Buffer Latency".

Another option to bypass Wine's audio stack is to use the UPnP media renderer output and have a receiver running on the same machine. The only downside is that visualisations won't work.
Title: Re: foo_out_pulse - pulseaudio output
Post by: marspeople on 2020-09-11 16:11:03
The intention of this component was definitely to try and fix that. Wine does seem to have some problems with audio but this bypasses the normal wine audio stack completely. Of course there still could be problems but as long as foobar doesn't get hung up by Wine for longer than the buffer length, in theory there shouldn't be any dropouts, but clearly it's not helping as much as I hoped. You could try increasing the buffer in foobar's Output settings (as this directly controls the Pulseaudio buffer) and check how long the buffer is when it's playing something, running pactl list sink-inputs and looking for "Buffer Latency".

Another option to bypass Wine's audio stack is to use the UPnP media renderer output and have a receiver running on the same machine. The only downside is that visualisations won't work.

I investigated the problem further. Indeed, it does NOT happen only with foobar but with any audio player! I listen mostly to foobar on this machine, so I assumed it was related to it.

So now to fix the general audio problem I found some suggestions to change scheduler settings in Pulseaudio. I tried and it seemed to have fixed the issue (so far). Even if it comes back, now I know where the problem might be. Thanks a lot for your help!
Title: Re: foo_out_pulse - pulseaudio output
Post by: sammoth on 2020-09-11 16:42:58
So now to fix the general audio problem I found some suggestions to change scheduler settings in Pulseaudio. I tried and it seemed to have fixed the issue (so far). Even if it comes back, now I know where the problem might be. Thanks a lot for your help!

Yep, changing the scheduler is necessary for me to get problem-free playback too. Glad it's working!
Title: Re: foo_out_pulse - pulseaudio output
Post by: sammoth on 2020-09-27 23:29:30
I released a small update with two fixes.

One is that I was noticing occasional crashes when stopping playback, where foobar would just instantly quit and not run the crash reporter. As far as I can tell it's due to a bug in the Windows code in Pulseaudio. For the moment I have added a workaround and it seems more stable for me.

The other change is that you can now configure the prebuffer length (amount of audio send to Pulseaudio before playback starts), and the default is shorter. Before, pulseaudio was left to choose a value automatically and it seemed to always choose the largest possible amount. For most files this wasn't noticeable as foobar could quickly decode enough audio. But for certain files, especially video where foobar is slower to decode, it would result in slow start of playback and slow seeking.

Download (https://github.com/sammoth/foo_out_pulse/releases)
Title: Re: foo_out_pulse - pulseaudio output
Post by: dkg on 2020-09-28 19:36:45
Hi.  I'm trying this component out for the first time.  When I try to play, I get "Error: Pulseaudio: connection failed: Access denied" in the console.  PulseAudio is running (only once), 'pactl list' shows a bunch of stuff.  The 'mpv' test command mentioned earlier works fine.  Was there some other fix I've missed?  Thanks.
Title: Re: foo_out_pulse - pulseaudio output
Post by: sammoth on 2020-09-28 19:39:35
Hi.  I'm trying this component out for the first time.  When I try to play, I get "Error: Pulseaudio: connection failed: Access denied" in the console.  PulseAudio is running (only once), 'pactl list' shows a bunch of stuff.  The 'mpv' test command mentioned earlier works fine.  Was there some other fix I've missed?  Thanks.

Did you follow the instructions in the readme about copying the pulseaudio cookie into your wine prefix?
Title: Re: foo_out_pulse - pulseaudio output
Post by: dkg on 2020-09-28 20:33:19
Did you follow the instructions in the readme about copying the pulseaudio cookie into your wine prefix?

Hmmm.  A file already existed at the destination.  So, I'm guessing that the 'ln -s' failed and I didn't notice somehow.  Anyway, the symlink is there now, but I'm getting the same result after restarting pulse and foobar.
Title: Re: foo_out_pulse - pulseaudio output
Post by: sammoth on 2020-09-28 20:46:43
OK, maybe try copying the file first instead of linking in case Wine isn't following symlinks. And, I'm pretty sure the location I give is where it will look for the cookie, but you could also try "C:\Users\<you>\.pulse-cookie" which I have seen it use in an older version. Maybe PA's cookie on Linux is in a different place? Seems unlikely but you could check "pulseaudio --dump-conf | grep cookie"

Failing that I'm not sure, you could also use IP-based authentication instead by changing the module parameters like:

load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1

Note that it's not very secure as it allows any user access to your pulseaudio daemon, or maybe even other things that shouldn't be able to access it.
Title: Re: foo_out_pulse - pulseaudio output
Post by: dkg on 2020-09-28 21:41:17
OK, maybe try copying the file first instead of linking in case Wine isn't following symlinks. And, I'm pretty sure the location I give is where it will look for the cookie, but you could also try "C:\Users\<you>\.pulse-cookie" which I have seen it use in an older version.

No dice with either of these.  The fact there was a file in the Windows location suggests it was looking there, too.

Maybe PA's cookie on Linux is in a different place? Seems unlikely but you could check "pulseaudio --dump-conf | grep cookie"

I think you're onto something!  The ~/.config/pulse/cookie file has an old date.  And, while, 'pulseaudio --dump-conf' works, there is no mention of a cookie.
Title: Re: foo_out_pulse - pulseaudio output
Post by: dkg on 2020-09-28 21:52:15
Hmmm.  I removed the cookie, then restarted pulseaudio.  It created a new cookie in that location.  It's got to be the right file.
Title: Re: foo_out_pulse - pulseaudio output
Post by: sammoth on 2020-09-28 21:54:00
You can check if foobar is trying to load a cookie, using something like this (but change the paths to match your wine prefix):

Code: [Select]
WINEPREFIX=/path/to/your/wine/prefix strace -e file "/path/to/your/wine/prefix/drive_c/Program Files/foobar2000/foobar2000.exe" 2>&1 | grep -i cookie

If they match then, I am stumped. I'd just try the IP auth method.
Title: Re: foo_out_pulse - pulseaudio output
Post by: dkg on 2020-09-28 22:11:47
Code: [Select]
WINEPREFIX=/home/dave/.wine/ strace -e file wine "/home/dave/.wine/drive_c/users/dave/AppData/Local/foobar2000/foobar2000.exe" 2>&1 | grep -i cookie
stat64("/home/dave/.wine/dosdevices/c:/users/dave/Cookies", {st_mode=S_IFDIR|0700, st_size=4096, ...}) = 0
lstat64("/home/dave/.wine/dosdevices/c:/users/dave/Cookies", {st_mode=S_IFDIR|0700, st_size=4096, ...}) = 0
Failed to read cookie file 'C:\users\dave\.config\pulse\cookie': Unknown error 10009
Failed to read cookie file 'C:\users\dave\.config\pulse\cookie': Unknown error 10009
Failed to load cookie file from cookie: Unknown error 10009

Same result no matter whether it's a symlink or a copy of the file.   I also changed permissions on the copy to 644 to make sure there was no permissions problem.  I already tried the IP auth method you mentioned.  It did work, but I needed to see if I could work out the security implications before I set it permanently.
Title: Re: foo_out_pulse - pulseaudio output
Post by: dkg on 2020-09-28 22:22:59
I have a feeling there is nothing wrong with the plugin code.  Here is more context from a full log.

Code: [Select]
00c3:fixme:msvcp:_Locinfo__Locinfo_ctor_cat_cstr (0891F4FC 1 C) semi-stub
00c3:err:msvcrt:msvcrt_get_flags incorrect mode flag: e
00c3:err:msvcrt:msvcrt_get_flags incorrect mode flag: e
00c3:err:msvcrt:msvcrt_get_flags incorrect mode flag: e
Failed to read cookie file 'C:\users\dave\.config\pulse\cookie': Unknown error 10009
Failed to read cookie file 'C:\users\dave\.config\pulse\cookie': Unknown error 10009
Failed to load cookie file from cookie: Unknown error 10009

I would be interested to see what strace shows for a working installation.
Title: Re: foo_out_pulse - pulseaudio output
Post by: sammoth on 2020-09-28 22:41:01
Hmm, there is no output from strace there for the cookie so it's not reading the file. When I run it I get:

openat(AT_FDCWD, "/home/sam/.config/pulse/cookie", O_RDONLY|O_NOCTTY|O_LARGEFILE|O_CLOEXEC) = 80

10009 seems to mean "The file handle supplied is not valid", maybe the path is inaccessible or wrong, or it could just be a bug in the pulseaudio code even if the path is correct. Are you sure the path is definitely right, ie /home/dave/.wine/drive_c/users/dave/.config/pulse/cookie ? I can't really think of anything else to try at the moment but I will reply if I do.
Title: Re: foo_out_pulse - pulseaudio output
Post by: dkg on 2020-09-29 00:51:02
Code: [Select]
$ ls -l /home/dave/.wine/drive_c/users/dave/.config/pulse/cookie
-rw-r--r-- 1 dave dave 256 Sep 28 14:04 /home/dave/.wine/drive_c/users/dave/.config/pulse/cookie

As long as pulseaudio is running as me, and 'ps' says it is, I don't see how the path could be inaccessible.  It's accessible to me.  I can also see the file in Wine Explorer and open it in Wine Notepad, exactly in the Windows path shown in the strace.  I wonder if the path isn't getting translated from Windows to linux where it should.  That's what I was hoping to see from a working strace.  But I don't know if the messages are comparable.

In the Wine Console:

Code: [Select]
H:\>dir C:\users\dave\.config\pulse\cookie
Volume in drive C has no label.
Volume Serial Number is c9e2-747b

Directory of C:\users\dave\.config\pulse

 9/28/2020   2:04 PM           256  cookie
       1 file                       256 bytes
       0 directories    239,606,796,288 bytes free

Same thing with 'type' shows unreadable garbage, obviously, but it does read the file. The following is from 'WINEDEBUG=warn+all' without strace:

Code: [Select]
00c7:warn:winsock:wsaErrno errno 115, (Operation now in progress).
00c7:err:msvcrt:msvcrt_get_flags incorrect mode flag: e
00c7:warn:ntdll:FILE_CreateFile L"\\??\\C:\\users\\dave\\.pulse\\client.conf" not found (c000003a)
00c7:warn:file:CreateFileW Unable to create file L"C:\\users\\dave\\.pulse\\client.conf" (status c000003a)
00c7:warn:msvcrt:MSVCRT__wsopen_dispatch :failed-last error (3)
00c7:err:msvcrt:msvcrt_get_flags incorrect mode flag: e
00c7:warn:ntdll:FILE_CreateFile L"\\??\\C:\\users\\dave\\.config\\pulse\\client.conf" not found (c0000034)
00c7:warn:file:CreateFileW Unable to create file L"C:\\users\\dave\\.config/pulse\\client.conf" (status c0000034)
00c7:warn:msvcrt:MSVCRT__wsopen_dispatch :failed-last error (2)
00c7:err:msvcrt:msvcrt_get_flags incorrect mode flag: e
00c7:warn:ntdll:FILE_CreateFile L"\\??\\C:\\users\\dave\\AppData\\Local\\foobar2000\\user-components\\foo_out_pulse\\pulse\\etc\\pulse\\client.conf" not found (c000003a)
00c7:warn:file:CreateFileW Unable to create file L"C:\\users\\dave\\AppData\\Local\\foobar2000\\user-components\\foo_out_pulse\\pulse\\etc\\pulse\\client.conf" (status c000003a)
00c7:warn:msvcrt:MSVCRT__wsopen_dispatch :failed-last error (3)
00c7:warn:ntdll:FILE_CreateFile L"\\??\\Z:\\usr\\i686-w64-mingw32\\share\\locale\\locale.alias" not found (c000003a)
00c7:warn:file:CreateFileW Unable to create file L"/usr/i686-w64-mingw32/share/locale/locale.alias" (status c000003a)
00c7:warn:msvcrt:MSVCRT__wsopen_dispatch :failed-last error (3)
00c7:warn:ntdll:FILE_CreateFile L"\\??\\C:\\users\\dave\\AppData\\Local\\share\\locale\\en_US.utf8\\LC_MESSAGES\\pulseaudio.mo" not found (c000003a)
00c7:warn:file:CreateFileW Unable to create file L"C:/users/dave/AppData/Local/share/locale/en_US.utf8/LC_MESSAGES/pulseaudio.mo" (status c000003a)
00c7:warn:msvcrt:MSVCRT__wsopen_dispatch :failed-last error (3)
00c7:warn:ntdll:FILE_CreateFile L"\\??\\C:\\users\\dave\\AppData\\Local\\share\\locale\\en_US\\LC_MESSAGES\\pulseaudio.mo" not found (c000003a)
00c7:warn:file:CreateFileW Unable to create file L"C:/users/dave/AppData/Local/share/locale/en_US/LC_MESSAGES/pulseaudio.mo" (status c000003a)
00c7:warn:msvcrt:MSVCRT__wsopen_dispatch :failed-last error (3)
00c7:warn:ntdll:FILE_CreateFile L"\\??\\C:\\users\\dave\\AppData\\Local\\share\\locale\\en.utf8\\LC_MESSAGES\\pulseaudio.mo" not found (c000003a)
00c7:warn:file:CreateFileW Unable to create file L"C:/users/dave/AppData/Local/share/locale/en.utf8/LC_MESSAGES/pulseaudio.mo" (status c000003a)
00c7:warn:msvcrt:MSVCRT__wsopen_dispatch :failed-last error (3)
00c7:warn:ntdll:FILE_CreateFile L"\\??\\C:\\users\\dave\\AppData\\Local\\share\\locale\\en\\LC_MESSAGES\\pulseaudio.mo" not found (c000003a)
00c7:warn:file:CreateFileW Unable to create file L"C:/users/dave/AppData/Local/share/locale/en/LC_MESSAGES/pulseaudio.mo" (status c000003a)
00c7:warn:msvcrt:MSVCRT__wsopen_dispatch :failed-last error (3)
00c7:warn:winsock:wsaErrno errno 115, (Operation now in progress).
Failed to read cookie file 'C:\users\dave\.config\pulse\cookie': Unknown error 10009
00c8:warn:ntdll:FILE_CreateFile L"\\??\\C:\\users\\dave\\.pulse-cookie" not found (c0000034)
00c8:warn:file:CreateFileW Unable to create file L"C:\\users\\dave\\.pulse-cookie" (status c0000034)
00c8:warn:msvcrt:MSVCRT__wsopen_dispatch :failed-last error (2)
00c8:warn:ntdll:FILE_CreateFile L"\\??\\C:\\users\\dave\\.config\\pulse" not found (c0000035)
Failed to read cookie file 'C:\users\dave\.config\pulse\cookie': Unknown error 10009
Failed to load cookie file from cookie: Unknown error 10009
00c8:warn:winsock:WS2_recv_base  -> ERROR 10035
Title: Re: foo_out_pulse - pulseaudio output
Post by: sammoth on 2020-09-29 01:00:17
Everything looks right to me..

Could you try with the first version from github, 0.1?
Title: Re: foo_out_pulse - pulseaudio output
Post by: dkg on 2020-09-29 02:00:25
Could you try with the first version from github, 0.1?

Sure!  Got this in the fb2k console:
Code: [Select]
Pulseaudio: Using Windows libpulse
Error: Pulseaudio: connection failed
Error: Pulseaudio: failed to connect
Unrecoverable playback error: Audio device invalidated

I also got a dialog that said "Unrecoverable playback error: Audio device invalidated".  Wine log and strace look about the same.

Here is something interesting.  I've been trying to turn up the pulseaudio client logging, so I created a 'client.conf' file in the same directory.  Since the entries below no longer appear in the log, I've concluded that it is finding and reading the file.

Code: [Select]
00bf:warn:ntdll:FILE_CreateFile L"\\??\\C:\\users\\dave\\AppData\\Local\\foobar2000\\user-components\\foo_out_pulse\\pulse\\etc\\pulse\\client.conf" not found (c000003a)
00bf:warn:file:CreateFileW Unable to create file L"C:\\users\\dave\\AppData\\Local\\foobar2000\\user-components\\foo_out_pulse\\pulse\\etc\\pulse\\client.conf" (status c000003a)

Since I'm not getting any more messages from the pulseaudio client, judging from the code, that could mean that it is successfully opening the cookie, but failing to read it.  On the other hand, I'm looking at v13 pulseaudio code, while you had to use an old version, and I don't know that it's really taking my logging change, anyway.  Unless you're willing to add some debug code to the pulseaudio source that you're compiling, I'm not sure how else to debug this.
Title: Re: foo_out_pulse - pulseaudio output
Post by: sammoth on 2020-09-29 02:09:41
Version 0.1 of the plugin uses pulseaudio 1.1 built by opensuse and the current version uses pulseaudio 13.0 built by me (so I was thinking there could be an issue with that build), but you can mix and match the libary dlls between versions of the plugin, the ABI is the same. I'm not sure why 0.1 won't connect, does it not connect with IP auth enabled either?

The code printing that error in PA looks a bit strange to me - it opens a file handle successfully and then as soon as it tries to read from it it gets 'file handle not valid'. Maybe I'm reading it wrong though. I'm not really sure what logging to add to that:

https://github.com/pulseaudio/pulseaudio/blob/4e3a080d7699732be9c522be9a96d851f97fbf11/src/pulsecore/authkey.c#L97

Could you give me your distribution/version and wine version? Maybe I can try in a VM.
Title: Re: foo_out_pulse - pulseaudio output
Post by: dkg on 2020-09-29 04:13:08
Version 0.1 of the plugin uses pulseaudio 1.1 built by opensuse and the current version uses pulseaudio 13.0 built by me (so I was thinking there could be an issue with that build), but you can mix and match the libary dlls between versions of the plugin, the ABI is the same. I'm not sure why 0.1 won't connect, does it not connect with IP auth enabled either?

Ah, I overlooked the part where you said you got v13 to build!  0.1 works with IP auth.  Without, the output looks more or less the same as your build.

Could you give me your distribution/version and wine version? Maybe I can try in a VM.

I'm certain you don't want to go there.  I'm running gentoo.  It would take considerable time and effort to set it all up.  Wine version is wine-vanilla 5.0.1.

If you're willing, these are the kinds of changes I had in mind.  I've made no attempt to run this through a compiler, so please forgive any syntax errors.

Code: [Select]
--- authkey.c.orig	2020-09-28 19:40:28.894629026 -0700
+++ authkey.c 2020-09-28 20:02:28.404587200 -0700
@@ -76,24 +76,29 @@
     int unlock = 0, ret = -1;
     ssize_t r;
 
+    pa_log("load() function, cookie filename: %s", fn);
     pa_assert(fn);
     pa_assert(data);
     pa_assert(length > 0);
 
     if (create)
+        pa_log("About to call pa_make_secure_parent_dir()");
         pa_make_secure_parent_dir(fn, pa_in_system_mode() ? 0755U : 0700U, -1, -1, false);
 
+    pa_log("About to call pa_open_cloexec()");
     if ((fd = pa_open_cloexec(fn, (create ? O_RDWR|O_CREAT : O_RDONLY)|O_BINARY, S_IRUSR|S_IWUSR)) < 0) {
-
         if (!create || errno != EACCES || (fd = open(fn, O_RDONLY|O_BINARY)) < 0) {
-            pa_log_warn("Failed to open cookie file '%s': %s", fn, pa_cstrerror(errno));
+            pa_log("Failed to open cookie file '%s': %s", fn, pa_cstrerror(errno));
             goto finish;
         } else
+            pa_log("pa_open_cloexec() else condition");
             writable = 0;
     }
 
+    pa_log("About to call pa_lock_fd()");
     unlock = pa_lock_fd(fd, 1) >= 0;
 
+    pa_log("About to call pa_loop_read()");
     if ((r = pa_loop_read(fd, data, length, NULL)) < 0) {
         pa_log("Failed to read cookie file '%s': %s", fn, pa_cstrerror(errno));
         goto finish;
@@ -168,21 +173,26 @@
     ssize_t r;
     char *p;
 
+    pa_log("pa_authkey_save() function, cookie filename: %s", fn);
     pa_assert(fn);
     pa_assert(data);
     pa_assert(length > 0);
 
     if ((ret = normalize_path(fn, &p)) < 0)
         return ret;
+    pa_log("Normalized path: %s", fn);
 
+    pa_log("About to call pa_open_cloexec()");
     if ((fd = pa_open_cloexec(p, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR)) < 0) {
-        pa_log_warn("Failed to open cookie file '%s': %s", fn, pa_cstrerror(errno));
+        pa_log("Failed to open cookie file '%s': %s", fn, pa_cstrerror(errno));
         ret = -1;
         goto finish;
     }
 
+    pa_log("About to call pa_lock_fd()");
     unlock = pa_lock_fd(fd, 1) >= 0;
 
+    pa_log("About to call pa_loop_write()");
     if ((r = pa_loop_write(fd, data, length, NULL)) < 0 || (size_t) r != length) {
         pa_log("Failed to read cookie file '%s': %s", fn, pa_cstrerror(errno));
         ret = -1;
Title: Re: foo_out_pulse - pulseaudio output
Post by: sammoth on 2020-09-29 10:30:16
Here you go, this is your patch on top of git master.

For reference, I built this on Arch as follows (after installing mingw-w64 and some libraries, configure (ie. bootstrap.sh) tells you which ones you need if they're missing):

Code: [Select]
./bootstrap.sh --host=i686-w64-mingw32 --enable-shared --disable-static --disable-waveout --disable-orc
make -j16 LDFLAGS='-shared'

cp ./src/.libs/libpulsecommon-13.99.dll ./src/.libs/libpulse-0.dll ~/desktop/pa
cp /usr/i686-w64-mingw32/bin/{libFLAC-8.dll,libgcc_s_dw2-1.dll,libintl-8.dll,libiconv-2.dll,libogg-0.dll,libsndfile-1.dll,libssp-0.dll,libvorbis-0.dll,libvorbisenc-2.dll,libwinpthread-1.dll} ~/desktop/pa/
Title: Re: foo_out_pulse - pulseaudio output
Post by: dkg on 2020-09-29 19:12:30
Here you go, this is your patch on top of git master.

Thanks.  Would you mind reporting what output you get with this build?
Title: Re: foo_out_pulse - pulseaudio output
Post by: sammoth on 2020-09-29 19:14:40
When playing something, I just get

Code: [Select]
load() function, cookie filename: C:\users\sam\.config\pulse\cookie
About to call pa_open_cloexec()
About to call pa_lock_fd()
About to call pa_loop_read()
Title: Re: foo_out_pulse - pulseaudio output
Post by: dkg on 2020-09-29 19:42:26
Code: [Select]
load() function, cookie filename: C:\users\dave\.config\pulse\cookie
0134:warn:ntdll:FILE_CreateFile L"\\??\\C:\\users\\dave\\.config\\pulse" not found (c0000035)
About to call pa_open_cloexec()
About to call pa_lock_fd()
About to call pa_loop_read()
Failed to read cookie file 'C:\users\dave\.config\pulse\cookie': Unknown error 10009
load() function, cookie filename: C:\users\dave\.pulse-cookie
0134:warn:ntdll:FILE_CreateFile L"\\??\\C:\\users\\dave" not found (c0000035)

So essentially the same as yours, right up to the point where pa_loop_read() fails, and it moves on to the next location.  (I assume you fixed the bug in my patch that didn't open a block for the 'else' further up.)  Anyway, I'll continue to investigate.
Title: Re: foo_out_pulse - pulseaudio output
Post by: dkg on 2020-09-29 23:14:12
I can't make much sense of this.  One way or another, pa_open_cloexec() would be making at least one open() call.  Yet, no syscall shows up in the strace.  I can see that happening if there was a problem with the path conversion, for example.  But, surely, it would return a negative value in that case.  If wine swallowed the open() call and returned a negative value, I would get an additional message from load() in the log.  It's like wine is declining to pass on the open() call, while also reporting success.  As you can imagine, it's a challenge to search the wine bug database for a common word like "open".  I'll try to update wine sometime soon and try again.  What version are you running @sammoth?
Title: Re: foo_out_pulse - pulseaudio output
Post by: sammoth on 2020-09-30 00:15:12
I'm using wine staging 5.18 at the moment, but it was working on some previous versions and non-staging too.

edit: have you tried looking at wine's full debug log output? WINEDEBUG=+all
it's pretty verbose though...
Title: Re: foo_out_pulse - pulseaudio output
Post by: dkg on 2020-09-30 01:30:08
edit: have you tried looking at wine's full debug log output? WINEDEBUG=+all
it's pretty verbose though...

"Pretty verbose" is understating it. :)  Yes, I had let it run for something like 30 mins and the fb2k window never appeared.  All the while it was creating a log file in the hundreds of MB.  Then I killed it.
Title: Re: foo_out_pulse - pulseaudio output
Post by: dkg on 2020-09-30 07:36:45
I upgraded to wine-vanilla-5.18, and now it's working.  :D   I didn't think it was working at first, until I discovered that I needed to update the symlinks for both 'wine' AND 'wine-vanilla', the latter of which still pointed to 5.0.1 and was used by Dolphin by default.  D'oh!

Before the upgrade, I did actually get a WINEDEBUG=+all log.  I started by making a copy of fb2k and stripped it down to the bare minimum - simplest DUI, one playlist with one local file, no library, nothing but standard components and foo_out_pulse.  Then I could get a +all log in a minute or two.  Without getting into the dirty details, it went like this.  pa_read() called recv(), which rightly failed.  The subsequent WSAGetLastError() call returned 0x2719, which corresponds to WSAEBADF, instead of the WSAENOTSOCK error that the pulseaudio code was expecting.  That lead me to the following commit to Wine on 2020-07-27, which changed the translation of STATUS_INVALID_HANDLE from WSAEBADF to WSAENOTSOCK.
https://source.winehq.org/git/wine.git/commitdiff/587732acb7834a52a2af5bb45e59899ab8ec3f5d

The following appears in the release notes of the next version after, 5.14.

Quote
Alistair Leslie-Hughes (1):
      ws2_32: Correct returned error code for an invalid socket.

In conclusion, at last as far as wine-vanilla is concerned, a minimum of version 5.14 is required.  I don't think it made it into the 5.0.2 stable release that came a little later.  I don't see a patch for this in wine-staging immediately prior to 5.14, either.
Title: Re: foo_out_pulse - pulseaudio output
Post by: sammoth on 2020-09-30 12:41:35
Oh nice work! I will make a note of it on the readme.
SimplePortal 1.0.0 RC1 © 2008-2020