Open Morganamilo opened 4 years ago
I've looked into audio while developing the macOS version of this driver. It doesn't seem too complicated, but I'm not sure how to implement Linux audio devices in user mode.
I can connect my arctis 9x pro to my linux machine via bluetooth, but I'm stuck using the ad2p bluetooth interface, so I can't use the headset's mic. I used XOW to allow the xbox usb adapter to connect to my headset, but my I couldn't find the headset in linux. Is there anything specific you need help with in order to connect a headset using the xbox wireless adapter?
The first step would be to create input and output audio devices for the headset but I'm not even sure if that's possible from user mode on Linux. If this can only be done from kernel mode then it's impossible for me to implement this in xow.
hhhmmm... When I connect my headset I didn't see the device anywhere. So even if I were able to create the output and input devices, I couldn't link them to anything.
Yeah, this is way too much work for me right now, considering I don't even have a device/headset to test this with. I may implement this for a 1.0 release of xow.
I think you need a headset with 3.5mm to connect to the gamepad. Not a headset connect to the Linux OS directly.
Use xbox device as Pulseaudio audio sink and source . https://www.freedesktop.org/wiki/Software/PulseAudio/
That makes sense. I don't actually own a xbox controller so this doesn't work. I used to have a arctis 9x, but i've returned it since I wasn't able to use it wirelessly in linux (except for bluetooth).
I did some packet capturing and reverse engineered the important parts of the protocol:
Those things would have to be implemented in xow (using PulseAudio). The timing of the individual packets (8 ms) is VERY important (that might be the biggest problem).
Hi All, Thanks for this beautiful library, keep it up! I'm testing now on Ubuntu 18, wireless dongle slim and Turtle Beach 600. The pairing goes well, the device does not show anywhere (expected). Running ./xow I get this:
@LorenzoMinutolo I'm currently focusing on implementing the audio for the controllers first, I might consider supporting third-party headsets for a future release.
I've implemented experimental headphone support, available in the audio
branch (only audio output right now). I'm still working on it, so please don't be surprised if you hear any crackling noises. I only tested it on my 1708 controller.
Important notes: You will have to install the PulseAudio libraries to compile xow. The PulseAudio daemon is usually running as a user-service and refuses any connections from root accounts. That's why I've decided to convert xow's system-service to a user-service. You will have to uninstall the system-service (sudo systemctl
) before installing the user-service (systemctl --user
) as described in the updated README. Running xow manually is not recommended and will increase the discernable audio noise.
I just tried the audio
branch.
First I could not compile it, but after performing sudo apt-get install libpulse-dev
I could.
I also did
sudo systemctl stop xow.service
sudo systemctl disable xow.service
sudo make uninstall
of the other version before.
But I can not enable
or start
the audio
version:
desktop@sn970:~/xow$ sudo systemctl --user enable xow.service
Failed to get D-Bus connection: Verbindungsaufbau abgelehnt
desktop@sn970:~/xow$ sudo systemctl --user start xow.service
Failed to get D-Bus connection: Verbindungsaufbau abgelehnt
Running the audio
branch of xow manually (which is not recommended for the audio
branch) still works:
desktop@sn970:~/xow$ ./xow
INFO - xow v0.4-17-g6c8aa7c ©Severin v. W.
INFO - Dongle plugged in
INFO - Wireless address: 62:45:b4:fa:b0:d2
INFO - Dongle initialized
INFO - Controller '1' connected
INFO - Product ID: 02ea
INFO - Serial number: 02600021263813
The PulseAudio daemon is running (I don't know if this information is helpful):
desktop@sn970:~/xow$ ps -ef|grep -i pulse
pulse 646 1 0 15:52 ? 00:00:01 /usr/bin/pulseaudio --system --disallow-exit --daemonize=no --high-priority
@andreashuetter Make sure to run systemctl --user
without sudo
.
Well, the reason why I tried it with sudo
was that without sudo
I always got:
desktop@sn970:~/xow$ systemctl --user enable xow.service
Failed to execute operation: No such file or directory
But now I tried
systemctl --user enable /lib/systemd/user/xow.service
and this at least did not return any error message.
But it doesn't seem to work at all. After
systemctl --user enable /lib/systemd/user/xow.service
and
systemctl --user start xow.service
I rebooted the machine, and it says it's not active:
desktop@sn970:~/xow$ systemctl status xow
● xow.service
Loaded: not-found (Reason: No such file or directory)
Active: inactive (dead)
Silly me, of course systemctl status xow
is the wrong command in this case.
Of course, systemctl --user status xow
is the way to go here:
desktop@sn970:~/xow$ systemctl --user status xow
● xow.service - Xbox One Wireless Dongle Driver
Loaded: loaded (/lib/systemd/user/xow.service; enabled)
Active: active (running) since Mi 2020-04-15 18:24:30 CEST; 2min 44s ago
Main PID: 1409 (xow)
CGroup: /user.slice/user-1000.slice/user@1000.service/xow.service
└─1409 /usr/local/bin/xow
But after some trying I fear that this version of xow is not suited for SteamOS.
The thing is, when SteamOS gets started it always starts in Big Picture Mode and everything is run by the user steam
.
In Big Picture Mode there is no desktop, no terminal window and so on. Only the steam gui. But there is the possibility to exit from steam and launch a Gnome Desktop instead where you can have a terminal window, a browser and so on (but no steam). When you do this you get logged on as user desktop
.
So whenever I had to do something like checking out xow from github, compiling it and installing it, I did this as user desktop
. Calling sudo make install
and sudo systemctl enable xow
made sure that xow gets started by the system on startup. But when I do systemctl --user enable /lib/systemd/user/xow.service
as user desktop
this won't work on startup, because this user is not even logged on on startup (as I described, this user only can get logged on by closing the steam session and launching the Gnome desktop instead). So I thought that maybe I have to try this as user steam
(by performing sudo su - steam
and then systemctl --user enable /lib/systemd/user/xow.service
), but this is not possible because the user steam
has very few priviliges and is not allowed to perform such things.
I switched back to the (system-service) master
branch of xow now, because I think currently it's not possible to get the (user-service) audio
branch to work properly on SteamOS.
Hmm, I think you could try using the old xow.service
file with the new audio
branch. I've noticed that you're running PulseAudio as a system-wide daemon (--system
), whereas most modern Linux distribution start individual instances of PulseAudio for each user, so a system-service might even work in your specific case.
I tried on Fedora 31, built and worked up until I plugged in a pair of headphones, then crashed:
Kernel: 5.5.15-200.fc31.x86_64
2020-04-15 20:30:28 DEBUG - Opening device...
2020-04-15 20:30:28 INFO - Dongle plugged in
2020-04-15 20:30:28 DEBUG - Firmware already loaded, resetting...
2020-04-15 20:30:28 DEBUG - Firmware loaded
2020-04-15 20:30:28 DEBUG - ASIC version: 7632
2020-04-15 20:30:28 DEBUG - MAC version: 7662
2020-04-15 20:30:28 DEBUG - Chip id: 7612
2020-04-15 20:30:28 INFO - Wireless address: 62:45:b4:ee:94:05
2020-04-15 20:30:28 INFO - Dongle initialized
2020-04-15 20:30:30 DEBUG - Client associating: 7e:ed:8c:80:45:6f
2020-04-15 20:30:30 INFO - Controller '1' connected
2020-04-15 20:30:30 INFO - Product ID: 02ea
2020-04-15 20:30:30 DEBUG - Firmware version: 3.1.1221.0
2020-04-15 20:30:30 DEBUG - Hardware version: 1284.1.1.1
2020-04-15 20:30:30 INFO - Serial number: 03600187504835
2020-04-15 20:30:32 DEBUG - Battery type: 1, level: 3
2020-04-15 20:30:41 INFO - Product ID: 02f6
2020-04-15 20:30:41 DEBUG - Firmware version: 3.1.1221.0
2020-04-15 20:30:41 DEBUG - Hardware version: 1284.1.1.1
terminate called after throwing an instance of 'InputException'
what(): Error adding key code: Invalid argument
Aborted (core dumped)
Hmm, I think you could try using the old
xow.service
file with the newaudio
branch. I've noticed that you're running PulseAudio as a system-wide daemon (--system
), whereas most modern Linux distribution start individual instances of PulseAudio for each user, so a system-service might even work in your specific case.
I tried what you suggested: Using the old xow.service
file with the new audio
branch (on SteamOS).
The result is that the controllers work as expected, but when I plug in the headset, nothing happens (the controller is still working). I tried to select the headset for audio output, but it didn't appear anywhere.
I guess connecting the headset to the controller is supposed to lead to an additional audio sink beeing listed?
desktop@sn970:~$ pactl list sinks
Sink #0
State: SUSPENDED
Name: alsa_output.pci-0000_00_1f.3.analog-stereo
Description: Internes Audio Analog Stereo
Driver: module-alsa-card.c
Sample Specification: s16le 2ch 44100Hz
Channel Map: front-left,front-right
Owner Module: 1
Mute: yes
Volume: front-left: 5621 / 9% / -64,00 dB, front-right: 5621 / 9% / -64,00 dB
balance 0,00
Base Volume: 65536 / 100% / 0,00 dB
Monitor Source: alsa_output.pci-0000_00_1f.3.analog-stereo.monitor
Latency: 0 usec, configured 0 usec
Flags: HARDWARE HW_MUTE_CTRL HW_VOLUME_CTRL DECIBEL_VOLUME LATENCY
Properties:
alsa.resolution_bits = "16"
device.api = "alsa"
device.class = "sound"
alsa.class = "generic"
alsa.subclass = "generic-mix"
alsa.name = "ALC892 Analog"
alsa.id = "ALC892 Analog"
alsa.subdevice = "0"
alsa.subdevice_name = "subdevice #0"
alsa.device = "0"
alsa.card = "0"
alsa.card_name = "HDA Intel PCH"
alsa.long_card_name = "HDA Intel PCH at 0xdf220000 irq 130"
alsa.driver_name = "snd_hda_intel"
device.bus_path = "pci-0000:00:1f.3"
sysfs.path = "/devices/pci0000:00/0000:00:1f.3/sound/card0"
device.bus = "pci"
device.vendor.id = "8086"
device.vendor.name = "Intel Corporation"
device.product.id = "a170"
device.form_factor = "internal"
device.string = "front:0"
device.buffering.buffer_size = "352800"
device.buffering.fragment_size = "176400"
device.access_mode = "mmap+timer"
device.profile.name = "analog-stereo"
device.profile.description = "Analog Stereo"
device.description = "Internes Audio Analog Stereo"
alsa.mixer_name = "Realtek ALC892"
alsa.components = "HDA:10ec0892,19dab246,00100302"
module-udev-detect.discovered = "1"
device.icon_name = "audio-card-pci"
Profile:
analog-output: Analoge Ausgabe (priority: 9900)
analog-output-lineout: Line Out (priority: 9900, not available)
Aktive Profile: analog-output
Formats:
pcm
Sink #2
State: SUSPENDED
Name: alsa_output.pci-0000_01_00.1.hdmi-stereo-extra2
Description: HDA NVidia Digital Stereo (HDMI)
Driver: module-alsa-card.c
Sample Specification: s16le 2ch 44100Hz
Channel Map: front-left,front-right
Owner Module: 15
Mute: no
Volume: front-left: 65536 / 100% / 0,00 dB, front-right: 65536 / 100% / 0,00 dB
balance 0,00
Base Volume: 65536 / 100% / 0,00 dB
Monitor Source: alsa_output.pci-0000_01_00.1.hdmi-stereo-extra2.monitor
Latency: 0 usec, configured 0 usec
Flags: HARDWARE DECIBEL_VOLUME LATENCY SET_FORMATS
Properties:
alsa.resolution_bits = "16"
device.api = "alsa"
device.class = "sound"
alsa.class = "generic"
alsa.subclass = "generic-mix"
alsa.name = "HDMI 2"
alsa.id = "HDMI 2"
alsa.subdevice = "0"
alsa.subdevice_name = "subdevice #0"
alsa.device = "8"
alsa.card = "1"
alsa.card_name = "HDA NVidia"
alsa.long_card_name = "HDA NVidia at 0xdf080000 irq 17"
alsa.driver_name = "snd_hda_intel"
device.bus_path = "pci-0000:01:00.1"
sysfs.path = "/devices/pci0000:00/0000:00:01.0/0000:01:00.1/sound/card1"
device.bus = "pci"
device.vendor.id = "10de"
device.vendor.name = "NVIDIA Corporation"
device.product.id = "0fbb"
device.string = "hdmi:1,2"
device.buffering.buffer_size = "352768"
device.buffering.fragment_size = "176384"
device.access_mode = "mmap+timer"
device.profile.name = "hdmi-stereo-extra2"
device.profile.description = "Digital Stereo (HDMI)"
device.description = "HDA NVidia Digital Stereo (HDMI)"
alsa.mixer_name = "Nvidia GPU 71 HDMI/DP"
alsa.components = "HDA:10de0071,19dab282,00100100"
module-udev-detect.discovered = "1"
device.icon_name = "audio-card-pci"
Profile:
hdmi-output-2: HDMI / DisplayPort 3 (priority: 5700, available)
Aktive Profile: hdmi-output-2
Formats:
pcm
When I stop the xow service and start xow manually to get more info then it keeps printing that it has detected the audio device, but never stops printing this (even if I disconnect the headphone it keeps printing these lines) until I press Ctrl+C:
desktop@sn970:~$ sudo systemctl stop xow
desktop@sn970:~$ /usr/local/bin/xow
INFO - xow v0.4-17-g6c8aa7c ©Severin v. W.
ERROR - Error creating lock file: Bad file descriptor
desktop@sn970:~$ sudo /usr/local/bin/xow
INFO - xow v0.4-17-g6c8aa7c ©Severin v. W.
INFO - Dongle plugged in
INFO - Wireless address: 62:45:b4:fa:b0:d2
INFO - Dongle initialized
INFO - Controller '1' connected
INFO - Product ID: 02ea
INFO - Serial number: 02600238452701
INFO - Accessory announced
INFO - Assuming it's an audio device
INFO - Accessory announced
INFO - Assuming it's an audio device
INFO - Accessory announced
INFO - Assuming it's an audio device
INFO - Accessory announced
INFO - Assuming it's an audio device
INFO - Accessory announced
INFO - Assuming it's an audio device
INFO - Accessory announced
INFO - Assuming it's an audio device
INFO - Accessory announced
INFO - Assuming it's an audio device
INFO - Accessory announced
INFO - Assuming it's an audio device
INFO - Accessory announced
INFO - Assuming it's an audio device
INFO - Accessory announced
INFO - Assuming it's an audio device
INFO - Accessory announced
INFO - Assuming it's an audio device
INFO - Accessory announced
INFO - Assuming it's an audio device
^C INFO - Dongle power-off
ERROR - Error in bulk read: LIBUSB_ERROR_NO_DEVICE
ERROR - Error in bulk read: LIBUSB_ERROR_NO_DEVICE
@TauAkiou It looks like it identified your headphones as an input device. I fixed this problem in the latest commit, but you might run into the same issue as @andreashuetter.
I guess connecting the headset to the controller is supposed to lead to an additional audio sink being listed?
Yes, it creates an audio sink for the controller's input (currently non-functional) and an audio source for the output. In your case, it seems to get stuck during the audio initialization (it should normally log Audio enabled
). Further analysis will definitely require a USB packet capture (on Windows), where you're plugging in the headphones, so I can find out why xow refuses to work.
Building audio branch and running xow from source directory I get the following output
❯ ./xow 2020-04-18 11:11:02 INFO - xow v0.4-19-gdfed4ea ©Severin v. W. 2020-04-18 11:11:02 DEBUG - Opening device... 2020-04-18 11:11:02 INFO - Dongle plugged in 2020-04-18 11:11:02 DEBUG - Firmware already loaded, resetting... 2020-04-18 11:11:02 DEBUG - Firmware loaded 2020-04-18 11:11:02 DEBUG - ASIC version: 7632 2020-04-18 11:11:02 DEBUG - MAC version: 7662 2020-04-18 11:11:02 DEBUG - Chip id: 7613 2020-04-18 11:11:02 INFO - Wireless address: 62:45:b5:10:74:a9 2020-04-18 11:11:02 INFO - Dongle initialized 2020-04-18 11:11:06 DEBUG - Client associating: 7e:ed:8c:45:0c:f7 2020-04-18 11:11:06 INFO - Controller '1' connected 2020-04-18 11:11:07 INFO - Device announced, id: 02dd 2020-04-18 11:11:07 DEBUG - Firmware version: 2.3.2385.0 2020-04-18 11:11:07 DEBUG - Hardware version: 2.1.1.1 2020-04-18 11:11:07 INFO - Device type: controller 2020-04-18 11:11:08 INFO - Device announced, id: 02e4 2020-04-18 11:11:08 DEBUG - Firmware version: 2.3.2385.0 2020-04-18 11:11:08 DEBUG - Hardware version: 2.1.1.1 2020-04-18 11:11:08 INFO - Device type: controller terminate called after throwing an instance of 'InputException' what(): Error adding key code: Invalid argument [1] 23864 abort ./xow
That's with headset plugged in; without it runs normally
@Aerol I've just pushed out a commit that should fix this issue.
@Aerol I've just pushed out a commit that should fix this issue.
It has indeed! Now getting more proper output
2020-04-18 13:35:39 DEBUG - Firmware version: 2.3.2385.0 2020-04-18 13:35:39 DEBUG - Hardware version: 2.1.1.1 2020-04-18 13:35:39 INFO - Device type: headset 2020-04-18 13:35:41 INFO - Device announced, id: 02e4
@andreashuetter Your issue should most likely be fixed now (didn't need the USB capture).
@andreashuetter Your issue should most likely be fixed now (didn't need the USB capture).
Thank you!
So I did some additional tests with your latest audio
commit.
This is what I did:
First I uninstalled xow completely and made sure there was no xow binary and no xow.service file anymore on my system.
Then I checked out the latest master
branch, compiled it and made
make BUILD=RELEASE
sudo make install
sudo systemctl enable xow.service
to get the proper service file.
After that I switched to the audio
branch, compiled that as well (but did no make install in order to keep the old service file) and copied the new audio binary manually into /usr/local/bin
overwriting the master xow binary:
git checkout audio
make clean
make BUILD=RELEASE
sudo cp xow /usr/local/bin/xow
sudo systemctl start xow
Result is that the controllers work as expected, but I still don't get an additional audio device when I plug in the headset into the controller. Stopping the xow service and starting it manually gives the following output:
desktop@sn970:~$ sudo systemctl stop xow
desktop@sn970:~$ cd xow
desktop@sn970:~/xow$ ./xow
INFO - xow v0.4-21-g070fbb7 ©Severin v. W.
ERROR - Error creating lock file: Bad file descriptor
desktop@sn970:~/xow$ sudo ./xow
INFO - xow v0.4-21-g070fbb7 ©Severin v. W.
INFO - Dongle plugged in
INFO - Wireless address: 62:45:b4:fa:b0:d2
INFO - Dongle initialized
INFO - Controller '1' connected
INFO - Device announced, product id: 02ea
INFO - Device type: controller
INFO - Serial number: 02600238452701
INFO - Device announced, product id: 0111
INFO - Device type: headset
INFO - Device announced, product id: 0111
INFO - Device type: headset
INFO - Device announced, product id: 0111
INFO - Device type: headset
INFO - Device announced, product id: 0111
INFO - Device type: headset
INFO - Device announced, product id: 0111
INFO - Device type: headset
INFO - Device announced, product id: 0111
INFO - Device type: headset
INFO - Device announced, product id: 0111
INFO - Device type: headset
INFO - Device announced, product id: 0111
INFO - Device type: headset
INFO - Device announced, product id: 0111
INFO - Device type: headset
INFO - Device announced, product id: 0111
...
Isn't there supposed to appear a new audio output device in my system config?
desktop@sn970:~$ pactl list sources
Source #1
State: SUSPENDED
Name: alsa_output.pci-0000_00_1f.3.analog-stereo.monitor
Description: Monitor of Internes Audio Analog Stereo
Driver: module-alsa-card.c
Sample Specification: s16le 2ch 44100Hz
Channel Map: front-left,front-right
Owner Module: 2
Mute: no
Volume: front-left: 65536 / 100% / 0,00 dB, front-right: 65536 / 100% / 0,00 dB
balance 0,00
Base Volume: 65536 / 100% / 0,00 dB
Monitor of Sink: alsa_output.pci-0000_00_1f.3.analog-stereo
Latency: 0 usec, configured 0 usec
Flags: DECIBEL_VOLUME LATENCY
Properties:
device.description = "Monitor of Internes Audio Analog Stereo"
device.class = "monitor"
alsa.card = "0"
alsa.card_name = "HDA Intel PCH"
alsa.long_card_name = "HDA Intel PCH at 0xdf220000 irq 130"
alsa.driver_name = "snd_hda_intel"
device.bus_path = "pci-0000:00:1f.3"
sysfs.path = "/devices/pci0000:00/0000:00:1f.3/sound/card0"
device.bus = "pci"
device.vendor.id = "8086"
device.vendor.name = "Intel Corporation"
device.product.id = "a170"
device.form_factor = "internal"
device.string = "0"
module-udev-detect.discovered = "1"
device.icon_name = "audio-card-pci"
Formats:
pcm
Source #2
State: RUNNING
Name: alsa_input.pci-0000_00_1f.3.analog-stereo
Description: Internes Audio Analog Stereo
Driver: module-alsa-card.c
Sample Specification: s16le 2ch 44100Hz
Channel Map: front-left,front-right
Owner Module: 2
Mute: yes
Volume: front-left: 11215 / 17% / -46,00 dB, front-right: 11215 / 17% / -46,00 dB
balance 0,00
Base Volume: 20724 / 32% / -30,00 dB
Monitor of Sink: k. A.
Latency: 423 usec, configured 20000 usec
Flags: HARDWARE HW_MUTE_CTRL HW_VOLUME_CTRL DECIBEL_VOLUME LATENCY
Properties:
alsa.resolution_bits = "16"
device.api = "alsa"
device.class = "sound"
alsa.class = "generic"
alsa.subclass = "generic-mix"
alsa.name = "ALC892 Analog"
alsa.id = "ALC892 Analog"
alsa.subdevice = "0"
alsa.subdevice_name = "subdevice #0"
alsa.device = "0"
alsa.card = "0"
alsa.card_name = "HDA Intel PCH"
alsa.long_card_name = "HDA Intel PCH at 0xdf220000 irq 130"
alsa.driver_name = "snd_hda_intel"
device.bus_path = "pci-0000:00:1f.3"
sysfs.path = "/devices/pci0000:00/0000:00:1f.3/sound/card0"
device.bus = "pci"
device.vendor.id = "8086"
device.vendor.name = "Intel Corporation"
device.product.id = "a170"
device.form_factor = "internal"
device.string = "front:0"
device.buffering.buffer_size = "352800"
device.buffering.fragment_size = "176400"
device.access_mode = "mmap+timer"
device.profile.name = "analog-stereo"
device.profile.description = "Analog Stereo"
device.description = "Internes Audio Analog Stereo"
alsa.mixer_name = "Realtek ALC892"
alsa.components = "HDA:10ec0892,19dab246,00100302"
module-udev-detect.discovered = "1"
device.icon_name = "audio-card-pci"
Profile:
analog-input: Analoge Eingabe (priority: 10000)
analog-input-mic: Mikrofon (priority: 8700, not available)
Aktive Profile: analog-input
Formats:
pcm
Source #3
State: IDLE
Name: alsa_output.pci-0000_01_00.1.hdmi-stereo-extra2.monitor
Description: Monitor of HDA NVidia Digital Stereo (HDMI)
Driver: module-alsa-card.c
Sample Specification: s16le 2ch 48000Hz
Channel Map: front-left,front-right
Owner Module: 1
Mute: no
Volume: front-left: 65536 / 100% / 0,00 dB, front-right: 65536 / 100% / 0,00 dB
balance 0,00
Base Volume: 65536 / 100% / 0,00 dB
Monitor of Sink: alsa_output.pci-0000_01_00.1.hdmi-stereo-extra2
Latency: 0 usec, configured 1837333 usec
Flags: DECIBEL_VOLUME LATENCY
Properties:
device.description = "Monitor of HDA NVidia Digital Stereo (HDMI)"
device.class = "monitor"
alsa.card = "1"
alsa.card_name = "HDA NVidia"
alsa.long_card_name = "HDA NVidia at 0xdf080000 irq 17"
alsa.driver_name = "snd_hda_intel"
device.bus_path = "pci-0000:01:00.1"
sysfs.path = "/devices/pci0000:00/0000:00:01.0/0000:01:00.1/sound/card1"
device.bus = "pci"
device.vendor.id = "10de"
device.vendor.name = "NVIDIA Corporation"
device.product.id = "0fbb"
device.string = "1"
module-udev-detect.discovered = "1"
device.icon_name = "audio-card-pci"
Formats:
pcm
Things seem to be working ok on my end with commit 070fbb7889cf7abe6f24b0fd4cd0e2f0aae1c4cb
I can even hear myself in my headset, but it seems to happen regardless of audio being muted in PA. Possibly something happening internally on the controller? I'm not 100% positive but I believe what needs to be created are a sink and source for audio to be routed to, not audio streams. We need to be able to tell pulseaudio to take audio from this device and send audio to the device etc.
What's currently being created is a playback stream to "generate audio" and send to a sink device (eg my soundcard output) and a recording stream that accepts audio input and does something with it
Possibly something happening internally on the controller?
Not that I'm aware of (I'm just using a standard smartphone headset). Input from the controller (microphone) is sent to a PulseAudio sink and output to the controller (headphones) is read from a PulseAudio source. The actual routing of the sink and source to your audio hardware is completely up to PulseAudio's configuration and can be changed via pavucontrol
.
What's currently being created is a playback stream to "generate audio" and send to a sink device (eg my soundcard output) and a recording stream that accepts audio input and does something with it.
Applications can only create sinks and sources (that's what xow is doing), but that should be sufficiently flexible to allow for different routing configurations.
Applications can only create sinks and sources (that's what xow is doing), but that should be sufficiently flexible to allow for different routing configurations.
Applications create playback and/or recording streams that can connect to device sinks and/or sources.
Input from the controller (microphone) is sent to a PulseAudio sink and output to the controller (headphones) is read from a PulseAudio source
I can connect the recording stream (PulseAudio source) created by xow to my main output monitor and can hear it in my headset, eg play music and I hear it in my headset.
If microphone audio is sent to the playback stream (PulseAudio sink) created by xow, all that would happen is microphone audio going out my desktop speakers. (mic audio is not picked up at the moment)
The way things are now, microphone can not be sent to Discord (or whatever;) and headphones can't receive audio from Discord (or whatever.) The xbox controller/xow needs to present itself to pulseaudio as an audio device (like JACK audio currently does on my system using a pulseaudio module), not an application trying to stream audio. Does this make sense?
Does this make sense?
Yes, makes perfect sense. I think I mixed up quite a lot of things in my last reply, sorry about that. When I did the initial research on how to create audio devices in Linux from user space, I came to the conclusion that the only way that would work would be to develop an ALSA kernel module. People suggested to use PulseAudio, but apparently it makes things even more complicated.
The only thing left that's worth trying out would be PulseAudio modules. I tried out module-pipe-source
and module-pipe-sink
and I guess it would be possible to load them at runtime via PulseAudio's API and redirect the controller's audio input/output to the modules' pipes. Does that sound like an idea? (pun intended)
Does that sound like an idea? (pun intended)
lol, yes; this does sound like a very usable idea.
I tried out
module-pipe-source
andmodule-pipe-sink
and I guess it would be possible to load them at runtime via PulseAudio's API and redirect the controller's audio input/output to the modules' pipes.
Regarding the redirection I want to point you to the module-switch-on-connect
module documented here for example. I use this for automatic output switching when connecting bluetooth headphones
So I was testing the audio branch with my controller and it works really well, obviously it can't send audio yet and that's fine for my use case, however there is one issue I noticed, and that's the fact that the controllers audio input doesn't create a new audio channel and it just hooks into the existing default, in my case the speakers, so audio is going through both my speakers and headphones connected to the controller. Any chance for the controller to create a new channel like it does on windows?
Any chance for the controller to create a new channel like it does on windows?
Yep, that's the plan. I'm currently working on other things, so I put this issue on hold for now.
@medusalix Awesome, glad to hear.
I just found xow today and would like to try out the experimental support. I'm unable to find the audio branch though. Why did you remove it?
@laurinneff The audio
branch had the same licensing-related issues as the master
branch, so I decided to remove it for now. I also ported some changes from audio
to master
, so the branches started to drift away from each other.
I plan on incorporating the feedback I got for an audio2
branch in the future after fixing some of the issues mentioned in earlier comments. I hope you understand.
@medusalix alright, I understand. Hope I can try it out soon
@medusalix may I ask you why did you decide to build audio support via Pulse Audio and not Alsa subsystem?
ALSA doesn't offer any option for user mode programs to hook into the audio system and create fully-featured audio devices at all. The only reason why we don't have audio support right now is the lack of a suitable API that would allow xow to expose the devices to the operating system (even with PulseAudio). Similar story for the missing upower
support by the way.
I don't think so. bluez-alsa is definitely userspace app and it creates sink device.
EDIT: There is a comment in the issue 48 that outlines other possible solutions via Alsa.
I know about bluez-alsa
, I even tried writing an Alsa PCM plugin for xow.
The point is that it simply doesn't behave like an audio card would. You can create sinks and sources that aplay
and arecord
can access. It's not exposed by PulseAudio and most applications can't even output to it. I need to create dedicated sound devices for xow, not a virtual device that you pipe your audio to.
Literally the only viable alternative would be PulseAudio modules, but they don't have a stable API.
OK, thank you Severin. I do not agree with you, nevertheless I accept your decision on your (actually nice) project. :+1: I do not use Pulse Audio at all, just Alsa and I do not have any problems with it. I do not know any app that does not with Alsa but Pulse Audio. In fact Pulse Audio could utilize underlying Alsa. Nevermind.
The problem is that applications like Discord show you a list of PulseAudio sinks and sources (at least if you've got PulseAudio installed). They simply don't give you an option to select which Alsa sink/source you want your output/input to go to. In fact, PulseAudio provides an Alsa device which allows legacy Alsa-only applications to interface with PulseAudio over their plugin.
Alsa PCM plugins unfortunately don't appear in PulseAudio's device list (at least to my knowledge) which means you have to use workarounds like aplay
to route your default audio output to the Alsa plugin on systems where PulseAudio is installed.
It's not a decision I've taken, it's more like a shortcoming of Alsa's (and PulseAudio's) design. I'm definitely open for suggestions, I don't want to limit myself to a specific audio system, I just want to make sure it's (1) as simple as possible to use and (2) it works on every system out there.
I examined audio branch from some repo that forked this one before when audio branch existed (sweet times :cry: ).
Basically, I think you made a good approach with simple API from PulseAudio (note that maybe async API will give better results. I managed to make some async API integration but as there were a lot of callbacks and controller needed to receive exact 0x600 bytes of data, that means threads and internal buffers implementation so I gave up for just POW case :smile: )
The only thing that should have been added that could be the key to the remaining problems is to create ALSA virtual device and connect with PulseAudio simple API to it. PulseAudio should automatically detect created ALSA virtual device so Discord user-case or any that needs PulseAudio should work. From there, PulseAudio simple(or async) API can be handled from xow and sent to controller(or to the virtual driver for mic).
Hi guys,
After a wild adventure with ALSA drivers, I gave up and found more simple solution:
After calling
pactl load-module module-null-sink sink_name=XboxOutput sink_properties=device.description="Xbox_controller_sink"
Another device will be added to the pulse audio.
In the xow code, the changes were:
sink = pa_simple_new(
nullptr,
name.c_str(),
PA_STREAM_PLAYBACK,
"XboxOutput1",
STREAM_NAME_SINK,
&config,
nullptr,
nullptr,
&error
);
and
source = pa_simple_new(
nullptr,
name.c_str(),
PA_STREAM_RECORD,
"XboxOutput1.monitor",
STREAM_NAME_SOURCE,
&config,
nullptr,
nullptr,
&error
);
Note: difference is that 4th parameter is changed from nullptr to the name of the module we created.
After this, the audio was able to play only on headphones after selecting them from PulseAudio menu.
For the microphone to work, there must be another module created only for microphone capture. If I understood correctly in xow there must be 2 use-cases detected: 1 is when controller is sending special packet with audio samples and is waiting for the dongle to return them (to establish connection from what I tested) 2 is when controller is sending audio from the mic (in this case we should send samples to other module so we don't hear ourselves and so we can select that specific module for input in the apps) So probably some special case should be if controller is connected or it is connecting.
Hope this is good progress for you and if you agree to integrate audio branch back with this changes included, I can continue on checking microphone pipeline that is needed. :smile:
Like I said in one of my earlier comments, I think if we're going to going to use PulseAudio's API for this then we'd be better of using module-pipe-sink
and module-pipe-source
directly instead of redirecting the audio through a null sink/source.
What bothers me the most is the fact that PulseAudio is by default running in local-user mode and only allows connections from your user account (not from root). That's the reason why I had to switch to a systemd
user service for the audio
branch. This will cause issues for multi-user systems because we can't have multiple instances of xow running at the same time. I don't think it makes much sense for a device driver to have per-user instances, as opposed to a single system-wide instance.
Now here's a solution that I'd imagine would work pretty well:
Either the suggestion outlined above or a dedicated PulseAudio module would work, I think.
I think that split-design is the best suggestion: Input devices should be created by system services because udev and logind already setup the permissions etc, connecting to pulse audio is a user service, so it needs to be the proxy between the xow system server and pulseaudio user service and it would probably be pretty light-weight. You could use dbus to signal the user service connection to the system daemon. For multiuser setups, there's "just" one thing to solve: You should track which user session currently claims the input device and only signal that particular user daemon. It should not be possible for other user sessions to "listen" to the audio.
Like I said in one of my earlier comments, I think if we're going to going to use PulseAudio's API for this then we'd be better of using module-pipe-sink and module-pipe-source directly instead of redirecting the audio through a null sink/source.
The problem with piping is that you must always have a reader on the other side or the reproduction of the sound will block. That can block write() function in xow if I am not mistaken.
This will cause issues for multi-user systems because we can't have multiple instances of xow running at the same time.
This is overthinking. If multi-user case is a big issue, a install script option that runs PulseAudio in system-wide mode can resolve this (if anybody actually cares if xow is system wide or not). No need to add another layer just for case that will probably never happen.
The problem with piping is that you must always have a reader on the other side or the reproduction of the sound will block. That can block write() function in xow if I am not mistaken.
According to pipe(7)
, a write
with O_NONBLOCK
set on the file descriptor should return EAGAIN
in case the FIFO buffer is already full (please correct me if I'm wrong). If we load the module with pa_context_load_module
the reader should be available right after the module is loaded.
This is overthinking. If multi-user case is a big issue, a install script option that runs PulseAudio in system-wide mode can resolve this.
You'd have to add an option that runs xow in system-wide mode though, not PA.
[...] if anybody actually cares if xow is system wide or not [...]
Would you expect your mouse or keyboard to turn off as soon as you logged out though? I certainly wouldn't. I believe nobody expects their input devices (or any device for that matter) to be bound to the lifetime of a specific user session. Oh, and there people who run multi-user systems (take a look at this comment).
I'm also curious about the (possible) issues that would arise by installing such a version of xow via a package manager like apt
. Would the command sudo apt install xow
be able to start the service for the current user? I don't know.
Would the command
sudo apt install xow
be able to start the service for the current user? I don't know.
Short answer: No... Long answer: apt
runs in root context, it could run systemctl enable --now xow-system.service
but that's it. The user would have to start it on its own. There's dbus activation for user services - not sure if it would work to activate a user service from a system service that way, I don't think so. But even then, the user session systemd must be reloaded to pick up the new service files. So: no. You'd need to re-login.
Also, I don't see why blocking in xow would be an issue as the writer could be implemented in a separate thread without blocking the main thread. It actually should be done that way. Also, the xow system service that receives the sound endpoint, doesn't even write directly to pa (except you manage to pass FDs around), it will probably be a proxy and should do reads and writes in separate threads anyways. The xow audio handler and input handler must be separate threads.
Does this driver support audio? Or are there plans to?