On 08/18/2017 06:55 AM, Andrew Eikum wrote:
Hey Jeremy, thanks for your interest! Like Austin said, I do most of the audio stuff in Wine these days, so you'll probably be working mostly with me.
Thank you for taking the time to reply. I noticed that a reply was going directly to you, instead of the mailing list, and so hit reply-all. If this was supposed to be an off-list conversation, I apologize, and will direct future replies directly to you.
First, I'd request that you try out the alternatives to implementing a driver. I don't know what your requirements are, but there are existing solutions for running PulseAudio on top of JACK. I'm not super familiar with JACK, but I think you'll want to follow the "Redirecting PulseAudio to JACK" section here[1], then make sure Wine is using the winepulse driver.
If that doesn't meet your requirements, you could also try redirecting winealsa to JACK, see[2,3]. This may have lower latency than running PA.
My use case is recording videos of applications running under Wine, often alongside my running commentary. I initially did use the winepulse driver, as most applications on my computer use PA for general sound (some require it). JACK gets used when I'm wanting to capture audio from my external audio interface, capture multiple sources synchronously so to reduce the amount of manual aligning I have to do when editing and mixing, or during said editing and mixing. As I run both Pulse and Jack, I initially was using the PA -> JACK setup you linked below[1], as it seemed the simplest/easiest solution.
However, I became displeased with that when I discovered that the PA -> JACK bridge was prone to random buffer under/over runs, even with relatively large buffer settings in JACK, and that it would drift out of sync over longer periods of time. I did take a look at the guides you linked at [3], but was left with the impression that doing so would bring even more complexity to the sound setup on my computer, leaving more opportunity for mis-configuration or breakage. It occurred to me that perhaps the Right Thing would be to have Wine talking to JACK natively. When I looked into this and found that Wine did have a JACK driver at one point previously, I thought, "It was done before. How hard could it be?" (Yes, I know that's a dangerous line of thinking :). )
The reason we resist adding new drivers is it adds a lot of work for the maintainers (i.e., me). I test each significant change to any part of our audio code on all four of our existing drivers (ALSA, OSS, PulseAudio, and macOS's CoreAudio), both by running the Wine unit tests and by testing all of the many audio applications I have that use the relevant APIs. On top of the testing itself, that means I have to understand how to run and maintain all four of those audio systems on my hardware. Further, any bug fixed or new feature added to one driver has to be understood and replicated in all other drivers, if applicable.
So you can see why I'd request you try existing solutions before jumping straight to a new audio driver. If you can convince me that existing solutions don't work for your requirements, then we can talk about adding a new driver to Wine. I'd at least like to be convinced that you've already tried alternatives and understand why they are unacceptable for your usecase.
I understand why you'd be reluctant to add another driver and can sympathize about maintenance burden it would impose. I'd hoped that if I could implement such a driver correctly, it wouldn't impose an undue maintenance burden, and the ability to now talk natively to JACK would be worth it. If you ultimately decide you do not want a JACK driver, I'm tempted to try to implement one anyway, even if it stays my own private patch and never makes it upstream. After looking at the Wine source and the JACK documentation, my curiosity is thoroughly piqued. Even if nothing ever comes of it, odds are I'll learn something, which is seldom a bad thing.
Once you get over that hurdle, you'll need to implement a winejack.drv similar to winealsa, winepulse, winecoreaudio, or wineoss. You'll want to copy whichever is closest to JACK's API and then modify it to use JACK. winealsa and wineoss operate in push mode (we maintain our own timers to keep the audio buffer full). winepulse and winecoreaudio are in pull mode (the audio system asks us to provide it with data). I don't recall which type of API JACK is.
I'll need to research this more to understand the distinction between the two. I know that JACK's API is implemented with callbacks, the main one being a process callback that JACK calls regularly when it wants a program to move data in or out of its buffers.
At a very high level, you'll need to implement all of the functions in the .spec file. You can look into the existing drivers to understand what those APIs do. The audio drivers export a few COM interfaces, which are used directly by applications or by dsound, winmm, and some other modules. The really important interfaces are IAudioClient, IAudioRenderClient, IAudioCaptureClient, and IAudioClock, and there are a few lesser-used interfaces besides.
Once you've implemented those interfaces, they'll need to pass the tests mentioned on the wiki page.
I noticed those .spec files in the driver sources. I've been trying to put together a mental model of how the drivers in Wine work. I noticed the first function on each line wasn't in the driver source file, but often the 2nd function was (though the ones in the MMDevAPI section do have nigh-identical names). Do I correctly understand that for a line in the .spec file, the first function listed is the function that will be called by MMDevAPi or the application, and the second one is the function that the former will be translated to? Do I correctly understand that the driver files thus contain the translated function calls, plus any additional necessary support functions and data structure needed for getting data to and from the audio system in question?
It occurs to me that since Wine interfaces with Windows applications, I might want to study the documentation for the Windows sound and driver APIs. Is this a correct assumption, or is this not particularly necessary in this case?
[1] https://github.com/jackaudio/jackaudio.github.com/wiki/WalkThrough_User_Puls...
[2] https://wiki.winehq.org/Sound#What_about_JACK.3F
[3] http://jackaudio.org/faq/routing_alsa.html
Andrew
Regards, Jeremy